RicardoMartins_PagSeguro - Version 3.0.1

Version Notes

Versão estável.

Os bugs devem ser reportados na área de Issues no github do projeto em https://github.com/r-martins/PagSeguro-Magento-Transparente

Download this release

Release Info

Developer Ricardo Martins
Extension RicardoMartins_PagSeguro
Version 3.0.1
Comparing to
See all releases


Code changes from version 2.5.6 to 3.0.1

Files changed (22) hide show
  1. app/code/community/RicardoMartins/PagSeguro/Helper/Data.php +46 -14
  2. app/code/community/RicardoMartins/PagSeguro/Helper/Internal.php +4 -1
  3. app/code/community/RicardoMartins/PagSeguro/Helper/Params.php +33 -7
  4. app/code/community/RicardoMartins/PagSeguro/Model/Abstract.php +98 -22
  5. app/code/community/RicardoMartins/PagSeguro/Model/Observer.php +1 -1
  6. app/code/community/RicardoMartins/PagSeguro/Model/Payment/Cc.php +35 -14
  7. app/code/community/RicardoMartins/PagSeguro/Model/Source/Ccbrand.php +26 -0
  8. app/code/community/RicardoMartins/PagSeguro/controllers/AjaxController.php +15 -0
  9. app/code/community/RicardoMartins/PagSeguro/controllers/TestController.php +68 -8
  10. app/code/community/RicardoMartins/PagSeguro/data/ricardomartins_pagseguro_setup/data-install-3.0.0.php +18 -0
  11. app/code/community/RicardoMartins/PagSeguro/etc/config.xml +17 -6
  12. app/code/community/RicardoMartins/PagSeguro/etc/system.xml +37 -5
  13. app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/cc.phtml +105 -0
  14. app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/cc/dob.phtml +87 -0
  15. app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/directpayment.phtml +14 -11
  16. app/design/frontend/base/default/template/ricardomartins_pagseguro/form/cc.phtml +26 -5
  17. app/design/frontend/base/default/template/ricardomartins_pagseguro/form/cc/dob.phtml +3 -3
  18. app/design/frontend/base/default/template/ricardomartins_pagseguro/form/directpayment.phtml +11 -12
  19. js/pagseguro/card.js +2495 -0
  20. js/pagseguro/pagseguro.js +221 -150
  21. package.xml +5 -5
  22. skin/frontend/base/default/pagseguro/selo/brflag.png +0 -0
app/code/community/RicardoMartins/PagSeguro/Helper/Data.php CHANGED
@@ -11,18 +11,24 @@
11
  */
12
  class RicardoMartins_PagSeguro_Helper_Data extends Mage_Core_Helper_Abstract
13
  {
14
- const XML_PATH_PAYMENT_PAGSEGURO_EMAIL = 'payment/pagseguro/merchant_email';
15
- const XML_PATH_PAYMENT_PAGSEGURO_TOKEN = 'payment/pagseguro/token';
16
- const XML_PATH_PAYMENT_PAGSEGURO_DEBUG = 'payment/pagseguro/debug';
17
- const XML_PATH_PAUMENT_PAGSEGURO_SANDBOX = 'payment/pagseguro/sandbox';
18
- const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_EMAIL = 'payment/pagseguro/sandbox_merchant_email';
19
- const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_TOKEN = 'payment/pagseguro/sandbox_token';
20
- const XML_PATH_PAYMENT_PAGSEGURO_WS_URL = 'payment/pagseguro/ws_url';
21
- const XML_PATH_PAYMENT_PAGSEGURO_WS_URL_APP = 'payment/pagseguro/ws_url_app';
22
- const XML_PATH_PAYMENT_PAGSEGURO_JS_URL = 'payment/pagseguro/js_url';
23
- const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_WS_URL = 'payment/pagseguro/sandbox_ws_url';
24
- const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_WS_URL_APP = 'payment/pagseguro/sandbox_ws_url_app';
25
- const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_JS_URL = 'payment/pagseguro/sandbox_js_url';
 
 
 
 
 
 
26
  const XML_PATH_PAYMENT_PAGSEGURO_KEY = 'payment/pagseguropro/key';
27
 
28
  /**
@@ -187,7 +193,7 @@ class RicardoMartins_PagSeguro_Helper_Data extends Mage_Core_Helper_Abstract
187
  */
188
  public function isCpfVisible()
189
  {
190
- $customerCpfAttribute = Mage::getStoreConfig('payment/pagseguro/customer_cpf_attribute');
191
  return empty($customerCpfAttribute);
192
  }
193
 
@@ -243,7 +249,7 @@ class RicardoMartins_PagSeguro_Helper_Data extends Mage_Core_Helper_Abstract
243
  public function checkTokenIntegrity()
244
  {
245
  $section = Mage::getSingleton('adminhtml/config')->getSection('payment');
246
- $frontendType = (string)$section->groups->pagseguro->fields->token->frontend_type;
247
 
248
  if ('obscure' != $frontendType) {
249
  $this->writeLog(
@@ -285,4 +291,30 @@ class RicardoMartins_PagSeguro_Helper_Data extends Mage_Core_Helper_Abstract
285
  );
286
  return $scriptBlock;
287
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
11
  */
12
  class RicardoMartins_PagSeguro_Helper_Data extends Mage_Core_Helper_Abstract
13
  {
14
+ const XML_PATH_PAYMENT_PAGSEGURO_EMAIL = 'payment/rm_pagseguro/merchant_email';
15
+ const XML_PATH_PAYMENT_PAGSEGURO_TOKEN = 'payment/rm_pagseguro/token';
16
+ const XML_PATH_PAYMENT_PAGSEGURO_DEBUG = 'payment/rm_pagseguro/debug';
17
+ const XML_PATH_PAUMENT_PAGSEGURO_SANDBOX = 'payment/rm_pagseguro/sandbox';
18
+ const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_EMAIL = 'payment/rm_pagseguro/sandbox_merchant_email';
19
+ const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_TOKEN = 'payment/rm_pagseguro/sandbox_token';
20
+ const XML_PATH_PAYMENT_PAGSEGURO_WS_URL = 'payment/rm_pagseguro/ws_url';
21
+ const XML_PATH_PAYMENT_PAGSEGURO_WS_URL_APP = 'payment/rm_pagseguro/ws_url_app';
22
+ const XML_PATH_PAYMENT_PAGSEGURO_JS_URL = 'payment/rm_pagseguro/js_url';
23
+ const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_WS_URL = 'payment/rm_pagseguro/sandbox_ws_url';
24
+ const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_WS_URL_APP = 'payment/rm_pagseguro/sandbox_ws_url_app';
25
+ const XML_PATH_PAYMENT_PAGSEGURO_SANDBOX_JS_URL = 'payment/rm_pagseguro/sandbox_js_url';
26
+ const XML_PATH_PAYMENT_PAGSEGURO_CC_ACTIVE = 'payment/rm_pagseguro_cc/active';
27
+ const XML_PATH_PAYMENT_PAGSEGURO_CC_FLAG = 'payment/rm_pagseguro_cc/flag';
28
+ const XML_PATH_PAYMENT_PAGSEGURO_CC_INFO_BRL = 'payment/rm_pagseguro_cc/info_brl';
29
+ const XML_PATH_PAYMENT_PAGSEGURO_CC_SHOW_TOTAL = 'payment/rm_pagseguro_cc/show_total';
30
+ const XML_PATH_PAYMENT_PAGSEGUROPRO_TEF_ACTIVE = 'payment/pagseguropro_tef/active';
31
+ const XML_PATH_PAYMENT_PAGSEGUROPRO_BOLETO_ACTIVE = 'payment/pagseguropro_boleto/active';
32
  const XML_PATH_PAYMENT_PAGSEGURO_KEY = 'payment/pagseguropro/key';
33
 
34
  /**
193
  */
194
  public function isCpfVisible()
195
  {
196
+ $customerCpfAttribute = Mage::getStoreConfig('payment/rm_pagseguro/customer_cpf_attribute');
197
  return empty($customerCpfAttribute);
198
  }
199
 
249
  public function checkTokenIntegrity()
250
  {
251
  $section = Mage::getSingleton('adminhtml/config')->getSection('payment');
252
+ $frontendType = (string)$section->groups->rm_pagseguro->fields->token->frontend_type;
253
 
254
  if ('obscure' != $frontendType) {
255
  $this->writeLog(
291
  );
292
  return $scriptBlock;
293
  }
294
+
295
+ /**
296
+ * Return serialized (json) string with module configuration
297
+ * return string
298
+ */
299
+ public function getConfigJs()
300
+ {
301
+ $config = array(
302
+ 'active_methods' => array(
303
+ 'cc' => (int)Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_PAGSEGURO_CC_ACTIVE),
304
+ 'boleto' => (int)Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_PAGSEGUROPRO_BOLETO_ACTIVE),
305
+ 'tef' => (int)Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_PAGSEGUROPRO_TEF_ACTIVE)
306
+ ),
307
+ 'flag' => Mage::getStoreConfig(self::XML_PATH_PAYMENT_PAGSEGURO_CC_FLAG),
308
+ 'debug' => $this->isDebugActive(),
309
+ 'PagSeguroSessionId' => $this->getSessionId(),
310
+ 'is_admin' => Mage::app()->getStore()->isAdmin(),
311
+ 'show_total' => Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_PAGSEGURO_CC_SHOW_TOTAL),
312
+ );
313
+ return json_encode($config);
314
+ }
315
+
316
+ public function isInfoBrlActive()
317
+ {
318
+ return Mage::getStoreConfigFlag(self::XML_PATH_PAYMENT_PAGSEGURO_CC_INFO_BRL);
319
+ }
320
  }
app/code/community/RicardoMartins/PagSeguro/Helper/Internal.php CHANGED
@@ -32,7 +32,10 @@ class RicardoMartins_PagSeguro_Helper_Internal extends Mage_Core_Helper_Abstract
32
  */
33
  public function getCreditCardApiCallParams(Mage_Sales_Model_Order $order, $payment)
34
  {
 
35
  $helper = Mage::helper('ricardomartins_pagseguro');
 
 
36
  $pHelper = Mage::helper('ricardomartins_pagseguro/params'); //params helper - helper auxiliar de parametrização
37
  $params = array(
38
  'email' => $helper->getMerchantEmail(),
@@ -41,7 +44,7 @@ class RicardoMartins_PagSeguro_Helper_Internal extends Mage_Core_Helper_Abstract
41
  'paymentMethod' => 'creditCard',
42
  'receiverEmail' => $helper->getMerchantEmail(),
43
  'currency' => 'BRL',
44
- 'creditCardToken' => $payment['additional_information']['credit_card_token'],
45
  'reference' => $order->getIncrementId(),
46
  'extraAmount' => $pHelper->getExtraAmount($order),
47
  'notificationURL' => Mage::getUrl('ricardomartins_pagseguro/notification'),
32
  */
33
  public function getCreditCardApiCallParams(Mage_Sales_Model_Order $order, $payment)
34
  {
35
+ /** @var RicardoMartins_PagSeguro_Helper_Data $helper */
36
  $helper = Mage::helper('ricardomartins_pagseguro');
37
+
38
+ /** @var RicardoMartins_PagSeguro_Helper_Params $pHelper */
39
  $pHelper = Mage::helper('ricardomartins_pagseguro/params'); //params helper - helper auxiliar de parametrização
40
  $params = array(
41
  'email' => $helper->getMerchantEmail(),
44
  'paymentMethod' => 'creditCard',
45
  'receiverEmail' => $helper->getMerchantEmail(),
46
  'currency' => 'BRL',
47
+ 'creditCardToken' => $pHelper->getPaymentHash('credit_card_token'),
48
  'reference' => $order->getIncrementId(),
49
  'extraAmount' => $pHelper->getExtraAmount($order),
50
  'notificationURL' => Mage::getUrl('ricardomartins_pagseguro/notification'),
app/code/community/RicardoMartins/PagSeguro/Helper/Params.php CHANGED
@@ -45,7 +45,6 @@ class RicardoMartins_PagSeguro_Helper_Params extends Mage_Core_Helper_Abstract
45
 
46
  $phone = $this->_extractPhone($order->getBillingAddress()->getTelephone());
47
 
48
-
49
  $senderName = $this->removeDuplicatedSpaces(
50
  sprintf('%s %s', $order->getCustomerFirstname(), $order->getCustomerLastname())
51
  );
@@ -55,7 +54,7 @@ class RicardoMartins_PagSeguro_Helper_Params extends Mage_Core_Helper_Abstract
55
  $return = array(
56
  'senderName' => $senderName,
57
  'senderEmail' => trim($order->getCustomerEmail()),
58
- 'senderHash' => $payment['additional_information']['sender_hash'],
59
  'senderCPF' => $digits->filter($cpf),
60
  'senderAreaCode'=> $phone['area'],
61
  'senderPhone' => $phone['number'],
@@ -138,10 +137,10 @@ class RicardoMartins_PagSeguro_Helper_Params extends Mage_Core_Helper_Abstract
138
  /** @var Mage_Sales_Model_Order_Address $address */
139
  $address = ($type=='shipping' && !$order->getIsVirtual()) ?
140
  $order->getShippingAddress() : $order->getBillingAddress();
141
- $addressStreetAttribute = Mage::getStoreConfig('payment/pagseguro/address_street_attribute');
142
- $addressNumberAttribute = Mage::getStoreConfig('payment/pagseguro/address_number_attribute');
143
- $addressComplementAttribute = Mage::getStoreConfig('payment/pagseguro/address_complement_attribute');
144
- $addressNeighborhoodAttribute = Mage::getStoreConfig('payment/pagseguro/address_neighborhood_attribute');
145
 
146
  //gathering address data
147
  $addressStreet = $this->_getAddressAttributeValue($address, $addressStreetAttribute);
@@ -415,7 +414,7 @@ class RicardoMartins_PagSeguro_Helper_Params extends Mage_Core_Helper_Abstract
415
  */
416
  private function _getCustomerCpfValue(Mage_Sales_Model_Order $order, $payment)
417
  {
418
- $customerCpfAttribute = Mage::getStoreConfig('payment/pagseguro/customer_cpf_attribute');
419
 
420
  if (empty($customerCpfAttribute)) { //Asked with payment data
421
  if (isset($payment['additional_information'][$payment->getMethod() . '_cpf'])) {
@@ -477,4 +476,31 @@ class RicardoMartins_PagSeguro_Helper_Params extends Mage_Core_Helper_Abstract
477
  }
478
  return (abs($extraAmount) == $totalAmount);
479
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  }
45
 
46
  $phone = $this->_extractPhone($order->getBillingAddress()->getTelephone());
47
 
 
48
  $senderName = $this->removeDuplicatedSpaces(
49
  sprintf('%s %s', $order->getCustomerFirstname(), $order->getCustomerLastname())
50
  );
54
  $return = array(
55
  'senderName' => $senderName,
56
  'senderEmail' => trim($order->getCustomerEmail()),
57
+ 'senderHash' => $this->getPaymentHash('sender_hash'),
58
  'senderCPF' => $digits->filter($cpf),
59
  'senderAreaCode'=> $phone['area'],
60
  'senderPhone' => $phone['number'],
137
  /** @var Mage_Sales_Model_Order_Address $address */
138
  $address = ($type=='shipping' && !$order->getIsVirtual()) ?
139
  $order->getShippingAddress() : $order->getBillingAddress();
140
+ $addressStreetAttribute = Mage::getStoreConfig('payment/rm_pagseguro/address_street_attribute');
141
+ $addressNumberAttribute = Mage::getStoreConfig('payment/rm_pagseguro/address_number_attribute');
142
+ $addressComplementAttribute = Mage::getStoreConfig('payment/rm_pagseguro/address_complement_attribute');
143
+ $addressNeighborhoodAttribute = Mage::getStoreConfig('payment/rm_pagseguro/address_neighborhood_attribute');
144
 
145
  //gathering address data
146
  $addressStreet = $this->_getAddressAttributeValue($address, $addressStreetAttribute);
414
  */
415
  private function _getCustomerCpfValue(Mage_Sales_Model_Order $order, $payment)
416
  {
417
+ $customerCpfAttribute = Mage::getStoreConfig('payment/rm_pagseguro/customer_cpf_attribute');
418
 
419
  if (empty($customerCpfAttribute)) { //Asked with payment data
420
  if (isset($payment['additional_information'][$payment->getMethod() . '_cpf'])) {
476
  }
477
  return (abs($extraAmount) == $totalAmount);
478
  }
479
+
480
+ /**
481
+ * Get payment hashes (sender_hash & credit_card_token) from session
482
+ * @param string $param sender_hash or credit_card_token
483
+ *
484
+ * @return bool|string
485
+ */
486
+ public function getPaymentHash($param=null)
487
+ {
488
+ $isAdmin = Mage::app()->getStore()->isAdmin();
489
+ $session = ($isAdmin)?'core/cookie':'checkout/session';
490
+ $registry = Mage::getSingleton($session);
491
+
492
+ $registry = ($isAdmin)?$registry->get('PsPayment'):$registry->getData('PsPayment');
493
+
494
+ $registry = unserialize($registry);
495
+
496
+ if (is_null($param)) {
497
+ return $registry;
498
+ }
499
+
500
+ if (isset($registry[$param])) {
501
+ return $registry[$param];
502
+ }
503
+
504
+ return false;
505
+ }
506
  }
app/code/community/RicardoMartins/PagSeguro/Model/Abstract.php CHANGED
@@ -11,6 +11,7 @@
11
  */
12
  class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_Abstract
13
  {
 
14
  /**
15
  * Processes notification XML data. XML is sent right after order is sent to PagSeguro, and on order updates.
16
  * @see https://pagseguro.uol.com.br/v2/guia-de-integracao/api-de-notificacoes.html#v2-item-servico-de-notificacoes
@@ -18,6 +19,13 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
18
  */
19
  public function proccessNotificatonResult(SimpleXMLElement $resultXML)
20
  {
 
 
 
 
 
 
 
21
  if (isset($resultXML->error)) {
22
  $errMsg = Mage::helper('ricardomartins_pagseguro')->__((string)$resultXML->error->message);
23
  Mage::throwException(
@@ -32,22 +40,24 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
32
  /** @var Mage_Sales_Model_Order $order */
33
  $order = Mage::getModel('sales/order')->loadByIncrementId((string)$resultXML->reference);
34
  $payment = $order->getPayment();
 
35
  $this->_code = $payment->getMethod();
36
  $processedState = $this->processStatus((int)$resultXML->status);
 
37
  $message = $processedState->getMessage();
38
 
39
  if ((int)$resultXML->status == 6) { //valor devolvido (gera credit memo e tenta cancelar o pedido)
40
  if ($order->canUnhold()) {
41
  $order->unhold();
42
  }
 
43
  if ($order->canCancel()) {
44
  $order->cancel();
45
  $order->save();
46
  } else {
47
  $payment->registerRefundNotification(floatval($resultXML->grossAmount));
48
  $order->addStatusHistoryComment(
49
- 'Devolvido: o valor foi devolvido ao comprador, mas o
50
- pedido encontra-se em um estado que não pode ser cancelado.'
51
  )->save();
52
  }
53
  }
@@ -67,28 +77,38 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
67
  }
68
 
69
  if ($processedState->getStateChanged()) {
70
- $order->setState(
71
- $processedState->getState(),
72
- true,
73
- $message,
74
- $processedState->getIsCustomerNotified()
75
- )->save();
 
 
 
 
76
  } else {
77
  $order->addStatusHistoryComment($message);
78
  }
79
 
80
  if ((int)$resultXML->status == 3) { //Quando o pedido foi dado como Pago
81
- //cria fatura e envia email (se configurado)
82
- // $payment->registerCaptureNotification(floatval($resultXML->grossAmount));
83
  if(!$order->hasInvoices()){
84
  $invoice = $order->prepareInvoice();
85
  $invoice->register()->pay();
86
  $msg = sprintf('Pagamento capturado. Identificador da Transação: %s', (string)$resultXML->code);
87
  $invoice->addComment($msg);
88
  $invoice->sendEmail(
89
- Mage::getStoreConfigFlag('payment/pagseguro/send_invoice_email'),
90
  'Pagamento recebido com sucesso.'
91
  );
 
 
 
 
 
 
92
  Mage::getModel('core/resource_transaction')
93
  ->addObject($invoice)
94
  ->addObject($invoice->getOrder())
@@ -132,7 +152,7 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
132
 
133
  $client->request();
134
  $resposta = $client->getLastResponse()->getBody();
135
-
136
  $helper->writeLog(sprintf('Retorno do Pagseguro para notificationCode %s: %s', $notificationCode, $resposta));
137
 
138
  libxml_use_internal_errors(true);
@@ -155,6 +175,7 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
155
  $return = new Varien_Object();
156
  $return->setStateChanged(true);
157
  $return->setIsTransactionPending(true); //payment is pending?
 
158
  switch($statusCode)
159
  {
160
  case '1':
@@ -204,7 +225,8 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
204
  );
205
  break;
206
  case '6':
207
- $return->setState(Mage_Sales_Model_Order::STATE_CLOSED);
 
208
  $return->setIsCustomerNotified(false);
209
  $return->setIsTransactionPending(false);
210
  $return->setMessage('Devolvida: o valor da transação foi devolvido para o comprador.');
@@ -226,10 +248,11 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
226
  * Call PagSeguro API to place an order (/transactions)
227
  * @param $params
228
  * @param $payment
 
229
  *
230
  * @return SimpleXMLElement
231
  */
232
- public function callApi($params, $payment)
233
  {
234
  $helper = Mage::helper('ricardomartins_pagseguro');
235
  $useApp = $helper->getLicenseType() == 'app';
@@ -238,11 +261,11 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
238
  }
239
  $params = $this->_convertEncoding($params);
240
  $paramsString = $this->_convertToCURLString($params);
241
-
242
- $helper->writeLog('Parametros sendo enviados para API (/transactions): '. var_export($params, true));
243
-
244
  $ch = curl_init();
245
- curl_setopt($ch, CURLOPT_URL, $helper->getWsUrl('transactions', $useApp));
246
  curl_setopt($ch, CURLOPT_POST, count($params));
247
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
248
  curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsString);
@@ -263,10 +286,11 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
263
  }
264
  curl_close($ch);
265
 
266
- $helper->writeLog('Retorno PagSeguro (/transactions): ' . var_export($response, true));
267
 
268
  libxml_use_internal_errors(true);
269
  $xml = simplexml_load_string(trim($response));
 
270
  if (false === $xml) {
271
  switch($response){
272
  case 'Unauthorized':
@@ -287,10 +311,60 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
287
  'Houve uma falha ao processar seu pedido/pagamento. Por favor entre em contato conosco.'
288
  );
289
  }
290
-
291
  return $xml;
292
  }
293
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  /**
295
  * Convert array values to utf-8
296
  * @param array $params
@@ -304,7 +378,7 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
304
  }
305
  return $params;
306
  }
307
-
308
  /**
309
  * Convert API params (already ISO-8859-1) to url format (curl string)
310
  * @param array $params
@@ -317,7 +391,9 @@ class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_
317
  foreach ($params as $k => $v) {
318
  $fieldsString .= $k.'='.urlencode($v).'&';
319
  }
320
-
321
  return rtrim($fieldsString, '&');
322
  }
323
  }
 
 
 
11
  */
12
  class RicardoMartins_PagSeguro_Model_Abstract extends Mage_Payment_Model_Method_Abstract
13
  {
14
+
15
  /**
16
  * Processes notification XML data. XML is sent right after order is sent to PagSeguro, and on order updates.
17
  * @see https://pagseguro.uol.com.br/v2/guia-de-integracao/api-de-notificacoes.html#v2-item-servico-de-notificacoes
19
  */
20
  public function proccessNotificatonResult(SimpleXMLElement $resultXML)
21
  {
22
+ // prevent this event from firing twice
23
+ if(Mage::registry('sales_order_invoice_save_after_event_triggered'))
24
+ {
25
+ return $this; // this method has already been executed once in this request
26
+ }
27
+ Mage::register('sales_order_invoice_save_after_event_triggered', true);
28
+
29
  if (isset($resultXML->error)) {
30
  $errMsg = Mage::helper('ricardomartins_pagseguro')->__((string)$resultXML->error->message);
31
  Mage::throwException(
40
  /** @var Mage_Sales_Model_Order $order */
41
  $order = Mage::getModel('sales/order')->loadByIncrementId((string)$resultXML->reference);
42
  $payment = $order->getPayment();
43
+
44
  $this->_code = $payment->getMethod();
45
  $processedState = $this->processStatus((int)$resultXML->status);
46
+
47
  $message = $processedState->getMessage();
48
 
49
  if ((int)$resultXML->status == 6) { //valor devolvido (gera credit memo e tenta cancelar o pedido)
50
  if ($order->canUnhold()) {
51
  $order->unhold();
52
  }
53
+
54
  if ($order->canCancel()) {
55
  $order->cancel();
56
  $order->save();
57
  } else {
58
  $payment->registerRefundNotification(floatval($resultXML->grossAmount));
59
  $order->addStatusHistoryComment(
60
+ 'Devolvido: o valor foi devolvido ao comprador.'
 
61
  )->save();
62
  }
63
  }
77
  }
78
 
79
  if ($processedState->getStateChanged()) {
80
+ // somente para o status 6 que edita o status do pedido - Weber
81
+ if ((int)$resultXML->status != 6) {
82
+ $order->setState(
83
+ $processedState->getState(),
84
+ true,
85
+ $message,
86
+ $processedState->getIsCustomerNotified()
87
+ )->save();
88
+ }
89
+
90
  } else {
91
  $order->addStatusHistoryComment($message);
92
  }
93
 
94
  if ((int)$resultXML->status == 3) { //Quando o pedido foi dado como Pago
95
+ // cria fatura e envia email (se configurado)
96
+ // $payment->registerCaptureNotification(floatval($resultXML->grossAmount));
97
  if(!$order->hasInvoices()){
98
  $invoice = $order->prepareInvoice();
99
  $invoice->register()->pay();
100
  $msg = sprintf('Pagamento capturado. Identificador da Transação: %s', (string)$resultXML->code);
101
  $invoice->addComment($msg);
102
  $invoice->sendEmail(
103
+ Mage::getStoreConfigFlag('payment/rm_pagseguro/send_invoice_email'),
104
  'Pagamento recebido com sucesso.'
105
  );
106
+
107
+ // salva o transaction id na invoice
108
+ if (isset($resultXML->code)) {
109
+ $invoice->setTransactionId((string)$resultXML->code)->save();
110
+ }
111
+
112
  Mage::getModel('core/resource_transaction')
113
  ->addObject($invoice)
114
  ->addObject($invoice->getOrder())
152
 
153
  $client->request();
154
  $resposta = $client->getLastResponse()->getBody();
155
+
156
  $helper->writeLog(sprintf('Retorno do Pagseguro para notificationCode %s: %s', $notificationCode, $resposta));
157
 
158
  libxml_use_internal_errors(true);
175
  $return = new Varien_Object();
176
  $return->setStateChanged(true);
177
  $return->setIsTransactionPending(true); //payment is pending?
178
+
179
  switch($statusCode)
180
  {
181
  case '1':
225
  );
226
  break;
227
  case '6':
228
+ //$return->setState(Mage_Sales_Model_Order::STATE_CLOSED);
229
+ $return->setData('state', Mage_Sales_Model_Order::STATE_CLOSED);
230
  $return->setIsCustomerNotified(false);
231
  $return->setIsTransactionPending(false);
232
  $return->setMessage('Devolvida: o valor da transação foi devolvido para o comprador.');
248
  * Call PagSeguro API to place an order (/transactions)
249
  * @param $params
250
  * @param $payment
251
+ * @param $type
252
  *
253
  * @return SimpleXMLElement
254
  */
255
+ public function callApi($params, $payment, $type='transactions')
256
  {
257
  $helper = Mage::helper('ricardomartins_pagseguro');
258
  $useApp = $helper->getLicenseType() == 'app';
261
  }
262
  $params = $this->_convertEncoding($params);
263
  $paramsString = $this->_convertToCURLString($params);
264
+
265
+ $helper->writeLog('Parametros sendo enviados para API (/'.$type.'): '. var_export($params, true));
266
+
267
  $ch = curl_init();
268
+ curl_setopt($ch, CURLOPT_URL, $helper->getWsUrl($type, $useApp));
269
  curl_setopt($ch, CURLOPT_POST, count($params));
270
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
271
  curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsString);
286
  }
287
  curl_close($ch);
288
 
289
+ $helper->writeLog('Retorno PagSeguro (/'.$type.'): ' . var_export($response, true));
290
 
291
  libxml_use_internal_errors(true);
292
  $xml = simplexml_load_string(trim($response));
293
+
294
  if (false === $xml) {
295
  switch($response){
296
  case 'Unauthorized':
311
  'Houve uma falha ao processar seu pedido/pagamento. Por favor entre em contato conosco.'
312
  );
313
  }
314
+
315
  return $xml;
316
  }
317
 
318
+ /**
319
+ * Check if order total is zero making method unavailable
320
+ * @param Mage_Sales_Model_Quote $quote
321
+ *
322
+ * @return mixed
323
+ */
324
+ public function isAvailable($quote = null)
325
+ {
326
+ return parent::isAvailable($quote) && !empty($quote)
327
+ && Mage::app()->getStore()->roundPrice($quote->getGrandTotal()) > 0;
328
+ }
329
+
330
+
331
+ /**
332
+ * Order payment
333
+ *
334
+ * @param Varien_Object $payment
335
+ * @param float $amount
336
+ *
337
+ * @return RicardoMartins_PagSeguro_Model_Payment_Abstract
338
+ */
339
+ public function refund(Varien_Object $payment, $amount)
340
+ {
341
+ //will grab data to be send via POST to API inside $params
342
+ $rmHelper = Mage::helper('ricardomartins_pagseguro');
343
+
344
+ // recupera a informação adicional do PagSeguro
345
+ $info = $this->getInfoInstance();
346
+ $transactionId = $info->getAdditionalInformation('transaction_id');
347
+
348
+ $params = array(
349
+ 'transactionCode' => $transactionId,
350
+ 'refundValue' => number_format($amount, 2, '.', ''),
351
+ );
352
+
353
+ if ($rmHelper->getLicenseType() != 'app') {
354
+ $params['token'] = $rmHelper->getToken();
355
+ $params['email'] = $rmHelper->getMerchantEmail();
356
+ }
357
+
358
+ // call API - refund
359
+ $returnXml = $this->callApi($params, $payment, 'transactions/refunds');
360
+
361
+ if ($returnXml === null) {
362
+ $errorMsg = $this->_getHelper()->__('Erro ao solicitar o reembolso.\n');
363
+ Mage::throwException($errorMsg);
364
+ }
365
+ return $this;
366
+ }
367
+
368
  /**
369
  * Convert array values to utf-8
370
  * @param array $params
378
  }
379
  return $params;
380
  }
381
+
382
  /**
383
  * Convert API params (already ISO-8859-1) to url format (curl string)
384
  * @param array $params
391
  foreach ($params as $k => $v) {
392
  $fieldsString .= $k.'='.urlencode($v).'&';
393
  }
 
394
  return rtrim($fieldsString, '&');
395
  }
396
  }
397
+
398
+
399
+
app/code/community/RicardoMartins/PagSeguro/Model/Observer.php CHANGED
@@ -20,7 +20,7 @@ class RicardoMartins_PagSeguro_Model_Observer
20
  $directpayment = Mage::app()->getLayout()
21
  ->createBlock('ricardomartins_pagseguro/form_directpayment')
22
  ->toHtml();
23
- $observer->getTransport()->setHtml($output . $directpayment);
24
  }
25
  return $this;
26
  }
20
  $directpayment = Mage::app()->getLayout()
21
  ->createBlock('ricardomartins_pagseguro/form_directpayment')
22
  ->toHtml();
23
+ $observer->getTransport()->setHtml($directpayment . $output);
24
  }
25
  return $this;
26
  }
app/code/community/RicardoMartins/PagSeguro/Model/Payment/Cc.php CHANGED
@@ -11,13 +11,14 @@
11
  */
12
  class RicardoMartins_PagSeguro_Model_Payment_Cc extends RicardoMartins_PagSeguro_Model_Abstract
13
  {
14
- protected $_code = 'pagseguro_cc';
15
  protected $_formBlockType = 'ricardomartins_pagseguro/form_cc';
16
  protected $_infoBlockType = 'ricardomartins_pagseguro/form_info_cc';
17
  protected $_isGateway = true;
18
  protected $_canAuthorize = true;
19
  protected $_canCapture = true;
20
- protected $_canRefund = false;
 
21
  protected $_canVoid = true;
22
  protected $_canUseInternal = false;
23
  protected $_canUseCheckout = true;
@@ -63,10 +64,14 @@ class RicardoMartins_PagSeguro_Model_Payment_Cc extends RicardoMartins_PagSeguro
63
  }
64
 
65
  $info = $this->getInfoInstance();
66
- $info->setAdditionalInformation('sender_hash', $data->getSenderHash())
67
- ->setAdditionalInformation('credit_card_token', $data->getCreditCardToken())
 
 
 
 
68
  ->setAdditionalInformation('credit_card_owner', $data->getPsCcOwner())
69
- ->setCcType($data->getPsCardType())
70
  ->setCcLast4(substr($data->getPsCcNumber(), -4));
71
 
72
  //cpf
@@ -111,26 +116,41 @@ class RicardoMartins_PagSeguro_Model_Payment_Cc extends RicardoMartins_PagSeguro
111
  public function validate()
112
  {
113
  parent::validate();
114
- $info = $this->getInfoInstance();
 
 
 
 
 
115
 
116
- $senderHash = $info->getAdditionalInformation('sender_hash');
117
- $creditCardToken = $info->getAdditionalInformation('credit_card_token');
 
 
 
 
 
118
 
119
- if (empty($creditCardToken) || empty($senderHash)) {
 
 
120
  Mage::helper('ricardomartins_pagseguro')
121
  ->writeLog(
122
- 'Falha ao obter o token do cartao ou sender_hash.
123
- Veja se os dados "sender_hash" e "credit_card_token" foram enviados no formulário.
124
- Um problema de JavaScript pode ter ocorrido.
125
- Se esta for apenas uma atualização de blocos via ajax nao se preocupe.'
126
  );
127
  Mage::throwException(
128
- 'Falha ao processar pagamento junto ao PagSeguro. Por favor, entre em contato com nossa equipe.'
129
  );
130
  }
131
  return $this;
132
  }
133
 
 
 
 
 
134
  /**
135
  * Order payment
136
  *
@@ -175,6 +195,7 @@ class RicardoMartins_PagSeguro_Model_Payment_Cc extends RicardoMartins_PagSeguro
175
  }
176
  }
177
  $payment->setAdditionalInformation($additional);
 
178
  }
179
  return $this;
180
  }
11
  */
12
  class RicardoMartins_PagSeguro_Model_Payment_Cc extends RicardoMartins_PagSeguro_Model_Abstract
13
  {
14
+ protected $_code = 'rm_pagseguro_cc';
15
  protected $_formBlockType = 'ricardomartins_pagseguro/form_cc';
16
  protected $_infoBlockType = 'ricardomartins_pagseguro/form_info_cc';
17
  protected $_isGateway = true;
18
  protected $_canAuthorize = true;
19
  protected $_canCapture = true;
20
+ protected $_canRefund = true;
21
+ protected $_canRefundInvoicePartial = false;
22
  protected $_canVoid = true;
23
  protected $_canUseInternal = false;
24
  protected $_canUseCheckout = true;
64
  }
65
 
66
  $info = $this->getInfoInstance();
67
+
68
+ /** @var RicardoMartins_PagSeguro_Helper_Params $pHelper */
69
+ $pHelper = Mage::helper('ricardomartins_pagseguro/params');
70
+
71
+ $info->setAdditionalInformation('sender_hash', $pHelper->getPaymentHash('sender_hash'))
72
+ ->setAdditionalInformation('credit_card_token', $pHelper->getPaymentHash('credit_card_token'))
73
  ->setAdditionalInformation('credit_card_owner', $data->getPsCcOwner())
74
+ ->setCcType($pHelper->getPaymentHash('cc_type'))
75
  ->setCcLast4(substr($data->getPsCcNumber(), -4));
76
 
77
  //cpf
116
  public function validate()
117
  {
118
  parent::validate();
119
+ $missingInfo = $this->getInfoInstance();
120
+
121
+ /** @var RicardoMartins_PagSeguro_Helper_Params $pHelper */
122
+ $pHelper = Mage::helper('ricardomartins_pagseguro/params');
123
+
124
+ $shippingMethod = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod();
125
 
126
+ // verifica se não há método de envio selecionado antes de exibir o erro de falha no cartão de crédito - Weber
127
+ if (empty($shippingMethod)) {
128
+ return false;
129
+ }
130
+
131
+ $senderHash = $pHelper->getPaymentHash('sender_hash');
132
+ $creditCardToken = $pHelper->getPaymentHash('credit_card_token');
133
 
134
+ if (!$creditCardToken || !$senderHash) {
135
+ $missingInfo = sprintf('Token do cartão: %s', var_export($creditCardToken, true));
136
+ $missingInfo .= sprintf('/ Sender_hash: %s', var_export($senderHash, true));
137
  Mage::helper('ricardomartins_pagseguro')
138
  ->writeLog(
139
+ "Falha ao obter o token do cartao ou sender_hash.
140
+ Ative o modo debug e observe o console de erros do seu navegador.
141
+ $missingInfo"
 
142
  );
143
  Mage::throwException(
144
+ 'Falha ao processar seu pagamento. Por favor, entre em contato com nossa equipe.'
145
  );
146
  }
147
  return $this;
148
  }
149
 
150
+
151
+ // public function processBeforeRefund($invoice, $payment){} //before refund
152
+ // public function processCreditmemo($creditmemo, $payment){} //after refund
153
+
154
  /**
155
  * Order payment
156
  *
195
  }
196
  }
197
  $payment->setAdditionalInformation($additional);
198
+
199
  }
200
  return $this;
201
  }
app/code/community/RicardoMartins/PagSeguro/Model/Source/Ccbrand.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PagSeguro Transparente Magento
4
+ *
5
+ * @category RicardoMartins
6
+ * @package RicardoMartins_PagSeguro
7
+ * @author Ricardo Martins
8
+ * @copyright Copyright (c) 2015 Ricardo Martins (http://r-martins.github.io/PagSeguro-Magento-Transparente/)
9
+ * @license https://opensource.org/licenses/MIT MIT License
10
+ */
11
+ class RicardoMartins_PagSeguro_Model_Source_Ccbrand
12
+ {
13
+ /**
14
+ * @return array
15
+ */
16
+ public function toOptionArray()
17
+ {
18
+ $options = array();
19
+ $options[] = array('value'=>'42x20','label'=>'42x20 px');
20
+ $options[] = array('value'=>'68x30','label'=>'68x30 px');
21
+ $options[] = array('value'=>'','label'=>'Exibir apenas texto');
22
+
23
+
24
+ return $options;
25
+ }
26
+ }
app/code/community/RicardoMartins/PagSeguro/controllers/AjaxController.php CHANGED
@@ -35,4 +35,19 @@ class RicardoMartins_PagSeguro_AjaxController extends Mage_Core_Controller_Front
35
  $this->getResponse()->setHeader('Content-type', 'application/json', true);
36
  $this->getResponse()->setBody(json_encode(array('session_id' => $sessionId)));
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
35
  $this->getResponse()->setHeader('Content-type', 'application/json', true);
36
  $this->getResponse()->setBody(json_encode(array('session_id' => $sessionId)));
37
  }
38
+
39
+ public function updatePaymentHashesAction()
40
+ {
41
+ $paymentPost = $this->getRequest()->getPost('payment');
42
+ $isAdmin = isset($paymentPost['is_admin']) && $paymentPost['is_admin']=="true";
43
+ $session = 'checkout/session';
44
+ if ($isAdmin) {
45
+ $session = 'core/cookie';
46
+ Mage::getSingleton($session)->set('PsPayment', serialize($paymentPost));
47
+ } else {
48
+ Mage::getSingleton($session)->setData('PsPayment', serialize($paymentPost));
49
+ }
50
+
51
+ $this->getResponse()->setHttpResponseCode(200);
52
+ }
53
  }
app/code/community/RicardoMartins/PagSeguro/controllers/TestController.php CHANGED
@@ -7,7 +7,7 @@
7
  * @category RicardoMartins
8
  * @package RicardoMartins_PagSeguro
9
  * @author Ricardo Martins
10
- * @copyright Copyright (c) 2015 Ricardo Martins (http://r-martins.github.io/PagSeguro-Magento-Transparente/)
11
  * @license https://opensource.org/licenses/MIT MIT License
12
  */
13
  class RicardoMartins_PagSeguro_TestController extends Mage_Core_Controller_Front_Action
@@ -19,19 +19,28 @@ class RicardoMartins_PagSeguro_TestController extends Mage_Core_Controller_Front
19
  public function getConfigAction()
20
  {
21
  $info = array();
 
 
 
22
  $info['RicardoMartins_PagSeguro']['version'] = (string)Mage::getConfig()
23
  ->getModuleConfig('RicardoMartins_PagSeguro')->version;
24
- $info['RicardoMartins_PagSeguro']['debug'] = Mage::getStoreConfigFlag('payment/pagseguro/debug');
25
- $info['RicardoMartins_PagSeguro']['sandbox'] = Mage::getStoreConfigFlag('payment/pagseguro/sandbox');
 
26
 
27
  if (Mage::getConfig()->getModuleConfig('RicardoMartins_PagSeguroPro')) {
28
  $info['RicardoMartins_PagSeguroPro']['version'] = (string)Mage::getConfig()
29
  ->getModuleConfig('RicardoMartins_PagSeguroPro')->version;
30
- $info['RicardoMartins_PagSeguroPro']['key_type'] =
31
- (string)Mage::getStoreConfig('payment/pagseguropro/key_type');
 
 
 
32
  }
33
 
34
- $helper = Mage::helper('ricardomartins_pagseguro');
 
 
35
  $info['session_id'] = $helper->getSessionId();
36
 
37
  $modules = array_keys((array)Mage::getConfig()->getNode('modules')->children());
@@ -41,8 +50,59 @@ class RicardoMartins_PagSeguro_TestController extends Mage_Core_Controller_Front
41
  $info['pagseguro_modules'][] = $module;
42
  }
43
  }
44
-
45
  $this->getResponse()->setHeader('Content-type', 'application/json');
46
- $this->getResponse()->setBody(json_encode($info));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
  }
7
  * @category RicardoMartins
8
  * @package RicardoMartins_PagSeguro
9
  * @author Ricardo Martins
10
+ * @copyright Copyright (c) 2017 Ricardo Martins (http://r-martins.github.io/PagSeguro-Magento-Transparente/)
11
  * @license https://opensource.org/licenses/MIT MIT License
12
  */
13
  class RicardoMartins_PagSeguro_TestController extends Mage_Core_Controller_Front_Action
19
  public function getConfigAction()
20
  {
21
  $info = array();
22
+ $helper = Mage::helper('ricardomartins_pagseguro');
23
+ $pretty = ($this->getRequest()->getParam('pretty', true) && version_compare(PHP_VERSION, '5.4', '>='))?128:0;
24
+
25
  $info['RicardoMartins_PagSeguro']['version'] = (string)Mage::getConfig()
26
  ->getModuleConfig('RicardoMartins_PagSeguro')->version;
27
+ $info['RicardoMartins_PagSeguro']['debug'] = Mage::getStoreConfigFlag('payment/rm_pagseguro/debug');
28
+ $info['RicardoMartins_PagSeguro']['sandbox'] = Mage::getStoreConfigFlag('payment/rm_pagseguro/sandbox');
29
+ $info['configJs'] = json_decode($helper->getConfigJs());
30
 
31
  if (Mage::getConfig()->getModuleConfig('RicardoMartins_PagSeguroPro')) {
32
  $info['RicardoMartins_PagSeguroPro']['version'] = (string)Mage::getConfig()
33
  ->getModuleConfig('RicardoMartins_PagSeguroPro')->version;
34
+
35
+ $keyType = $helper->getLicenseType();
36
+ $info['RicardoMartins_PagSeguroPro']['key_type'] = ($keyType)==''?'assinatura':$keyType;
37
+ $info['RicardoMartins_PagSeguroPro']['key_validation'] = $this->_validateKey($keyType);
38
+
39
  }
40
 
41
+ $info['compilation'] = $this->_getCompilerState();
42
+
43
+ $info['token_consistency'] = $this->_getTokenConsistency();
44
  $info['session_id'] = $helper->getSessionId();
45
 
46
  $modules = array_keys((array)Mage::getConfig()->getNode('modules')->children());
50
  $info['pagseguro_modules'][] = $module;
51
  }
52
  }
 
53
  $this->getResponse()->setHeader('Content-type', 'application/json');
54
+ $this->getResponse()->setBody(json_encode($info, $pretty));
55
+
56
+ }
57
+
58
+ /**
59
+ * Validates your PRO key. Only for tests purposes.
60
+ * @return mixed|string
61
+ */
62
+ private function _validateKey()
63
+ {
64
+ $key = Mage::getStoreConfig('payment/pagseguropro/key');
65
+ if (empty($key)) {
66
+ return 'KEY IS EMPTY';
67
+ }
68
+ $url = 'http://ws.ricardomartins.net.br/pspro/v6/auth/' . $key;
69
+
70
+ $ch = curl_init();
71
+ curl_setopt($ch, CURLOPT_URL, $url);
72
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
73
+ curl_setopt($ch, CURLOPT_TIMEOUT, 45);
74
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
75
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
76
+ libxml_use_internal_errors(true);
77
+
78
+ return curl_exec($ch);
79
+ }
80
+
81
+ /**
82
+ * Get compilation config details
83
+ * @return array
84
+ */
85
+ private function _getCompilerState()
86
+ {
87
+ $compiler = Mage::getModel('compiler/process');
88
+ $compilerConfig = MAGENTO_ROOT . '/includes/config.php';
89
+
90
+ if (file_exists($compilerConfig) && !(defined('COMPILER_INCLUDE_PATH') || defined('COMPILER_COLLECT_PATH'))) {
91
+ include $compilerConfig;
92
+ }
93
+ $status = defined('COMPILER_INCLUDE_PATH') ? 'Enabled' : 'Disabled';
94
+ $state = $compiler->getCollectedFilesCount() > 0 ? 'Compiled' : 'Not Compiled';
95
+ return array(
96
+ 'status' => $status,
97
+ 'state' => $state,
98
+ 'files_count' => $compiler->getCollectedFilesCount(),
99
+ 'scopes_count' => $compiler->getCompiledFilesCount()
100
+ );
101
+ }
102
+
103
+ private function _getTokenConsistency()
104
+ {
105
+ $token = Mage::helper('ricardomartins_pagseguro')->getToken();
106
+ return (strlen($token)!=32)?'Wrong size':'Good';
107
  }
108
  }
app/code/community/RicardoMartins/PagSeguro/data/ricardomartins_pagseguro_setup/data-install-3.0.0.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Migra configurações antigas(se houver) pro padrão novo, evitando conflitos com outros módulos PagSeguro
4
+ */
5
+
6
+ /* @var $installer Mage_Core_Model_Resource_Setup */
7
+ $installer = $this;
8
+
9
+ $token = Mage::getStoreConfig('payment/pagseguro/token');
10
+ $decryptedToken = Mage::helper('core')->decrypt($token);
11
+
12
+ if ($token != false && strlen($decryptedToken) == 32 ) {
13
+ $sql = "UPDATE {$this->getTable('core/config_data')}
14
+ SET path = REPLACE(path, 'payment/pagseguro/', 'payment/rm_pagseguro/')
15
+ WHERE path LIKE 'payment/pagseguro/%'";
16
+
17
+ $installer->getConnection()->query($sql);
18
+ }
app/code/community/RicardoMartins/PagSeguro/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <RicardoMartins_PagSeguro>
5
- <version>2.5.6</version>
6
  </RicardoMartins_PagSeguro>
7
  </modules>
8
  <global>
@@ -21,6 +21,14 @@
21
  <class>RicardoMartins_PagSeguro_Helper</class>
22
  </ricardomartins_pagseguro>
23
  </helpers>
 
 
 
 
 
 
 
 
24
  </global>
25
  <frontend>
26
  <routers>
@@ -63,18 +71,21 @@
63
  </adminhtml>
64
  <default>
65
  <payment>
66
- <pagseguro_cc>
67
  <active>0</active>
68
  <title>Cartão de Crédito - via PagSeguro UOL</title>
69
  <order_status>pending</order_status>
 
70
  <payment_action>order</payment_action>
71
  <model>ricardomartins_pagseguro/payment_cc</model>
72
  <allowspecific>0</allowspecific>
73
  <send_neworder_email>0</send_neworder_email>
74
  <!--<specificcountry>BR</specificcountry>-->
75
  <group_restriction>0</group_restriction>
76
- </pagseguro_cc>
77
- <pagseguro>
 
 
78
  <customer_cpf_attribute>taxvat</customer_cpf_attribute>
79
  <address_street_attribute>street_1</address_street_attribute>
80
  <address_number_attribute>street_2</address_number_attribute>
@@ -87,13 +98,13 @@
87
  <sandbox_ws_url_app>https://ws.ricardomartins.net.br/pspro/v6/wspagseguro/sandbox/v2/</sandbox_ws_url_app>
88
  <!--<sandbox_ws_url_app>http://ws.local.com.br/pspro/v6/wspagseguro/sandbox/v2/</sandbox_ws_url_app>-->
89
  <sandbox_js_url>https://stc.sandbox.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js</sandbox_js_url>
90
- </pagseguro>
91
  </payment>
92
  </default>
93
  <phpunit>
94
  <suite>
95
  <modules>
96
- <RicardoMartins_PagSeguro />
97
  </modules>
98
  </suite>
99
  </phpunit>
2
  <config>
3
  <modules>
4
  <RicardoMartins_PagSeguro>
5
+ <version>3.0.0</version>
6
  </RicardoMartins_PagSeguro>
7
  </modules>
8
  <global>
21
  <class>RicardoMartins_PagSeguro_Helper</class>
22
  </ricardomartins_pagseguro>
23
  </helpers>
24
+ <resources>
25
+ <ricardomartins_pagseguro_setup>
26
+ <setup>
27
+ <module>RicardoMartins_PagSeguro</module>
28
+ <class>Mage_Core_Model_Resource_Setup</class>
29
+ </setup>
30
+ </ricardomartins_pagseguro_setup>
31
+ </resources>
32
  </global>
33
  <frontend>
34
  <routers>
71
  </adminhtml>
72
  <default>
73
  <payment>
74
+ <rm_pagseguro_cc>
75
  <active>0</active>
76
  <title>Cartão de Crédito - via PagSeguro UOL</title>
77
  <order_status>pending</order_status>
78
+ <flag>42x20</flag>
79
  <payment_action>order</payment_action>
80
  <model>ricardomartins_pagseguro/payment_cc</model>
81
  <allowspecific>0</allowspecific>
82
  <send_neworder_email>0</send_neworder_email>
83
  <!--<specificcountry>BR</specificcountry>-->
84
  <group_restriction>0</group_restriction>
85
+ <info_brl>1</info_brl>
86
+ <total_installments>0</total_installments>
87
+ </rm_pagseguro_cc>
88
+ <rm_pagseguro>
89
  <customer_cpf_attribute>taxvat</customer_cpf_attribute>
90
  <address_street_attribute>street_1</address_street_attribute>
91
  <address_number_attribute>street_2</address_number_attribute>
98
  <sandbox_ws_url_app>https://ws.ricardomartins.net.br/pspro/v6/wspagseguro/sandbox/v2/</sandbox_ws_url_app>
99
  <!--<sandbox_ws_url_app>http://ws.local.com.br/pspro/v6/wspagseguro/sandbox/v2/</sandbox_ws_url_app>-->
100
  <sandbox_js_url>https://stc.sandbox.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js</sandbox_js_url>
101
+ </rm_pagseguro>
102
  </payment>
103
  </default>
104
  <phpunit>
105
  <suite>
106
  <modules>
107
+ <RicardoMartins_PagSeguro/>
108
  </modules>
109
  </suite>
110
  </phpunit>
app/code/community/RicardoMartins/PagSeguro/etc/system.xml CHANGED
@@ -29,8 +29,8 @@
29
  <sections>
30
  <payment>
31
  <groups>
32
- <pagseguro module="ricardomartins_pagseguro">
33
- <comment><![CDATA[Precisa de ajuda? - <a href="http://r-martins.github.io/PagSeguro-Magento-Transparente" target="_blank">Site oficial do módulo</a> | <a href="https://pagsegurotransparente.zendesk.com/hc/pt-br" target="_blank">Central de Ajuda</a></href><br/> Lembre-se de <a href="//r-martins.github.io/PagSeguro-Magento-Transparente/pro/app.html#contratar" target="_blank"><strong>autorizar sua conta</strong></a> com a aplicação do módulo para liberar o checkout transparente junto ao PagSeguro. Ao fazer isso você também receberá o módulo PRO gratuitamente no e-mail informado, com suporte a boleto e TEF.<br/>Se preferir não utilizar a aplicação, <a href="//pagseguro.uol.com.br/receba-pagamentos.jhtml#checkout-transparent" target="_blank">solicite ao PagSeguro</a> a liberação da sua conta manualmente. E se desejar receber o módulo PRO com suporte a boleto e tef sem autorizar a aplicação, <a href="//r-martins.github.io/PagSeguro-Magento-Transparente/pro/" target="_blank">faça uma assinatura</a>.]]></comment>
34
  <label>PagSeguro - Ricardo Martins</label>
35
  <frontend_type>text</frontend_type>
36
  <sort_order>110</sort_order>
@@ -47,6 +47,7 @@
47
  <show_in_website>1</show_in_website>
48
  <show_in_store>0</show_in_store>
49
  <comment>E-mail da loja (conta vendedor)</comment>
 
50
  </merchant_email>
51
  <token translate="label">
52
  <label>Token</label>
@@ -57,6 +58,7 @@
57
  <show_in_website>1</show_in_website>
58
  <show_in_store>0</show_in_store>
59
  <comment>O token é obtido no seu painel do PagSeguro. Ao salvar esta página, ele será criptografado, aparentando ter um tamanho menor.</comment>
 
60
  </token>
61
  <sandbox translate="label">
62
  <label>Ambiente de testes?</label>
@@ -202,8 +204,8 @@
202
  <comment><![CDATA[Caso sua loja utilize um atributo personalizado para o campo 'Bairro' de entrega, selecione aqui.]]></comment>
203
  </address_neighborhood_attribute>
204
  </fields>
205
- </pagseguro>
206
- <pagseguro_cc module="ricardomartins_pagseguro">
207
  <label>PagSeguro - Cartão de Crédito - Ricardo Martins</label>
208
  <frontend_type>text</frontend_type>
209
  <sort_order>111</sort_order>
@@ -240,6 +242,26 @@
240
  <show_in_website>1</show_in_website>
241
  <show_in_store>0</show_in_store>
242
  </order_status>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  <owner_dob_attribute>
244
  <label>Data de Nascimento</label>
245
  <frontend_type>select</frontend_type>
@@ -281,8 +303,18 @@
281
  <group_restriction>1</group_restriction>
282
  </depends>
283
  </customer_groups>
 
 
 
 
 
 
 
 
 
 
284
  </fields>
285
- </pagseguro_cc>
286
  </groups>
287
  </payment>
288
  </sections>
29
  <sections>
30
  <payment>
31
  <groups>
32
+ <rm_pagseguro module="ricardomartins_pagseguro">
33
+ <comment><![CDATA[Precisa de ajuda? - <a href="//r-martins.github.io/PagSeguro-Magento-Transparente" target="_blank">Site oficial do módulo</a> | <a href="//pagsegurotransparente.zendesk.com/hc/pt-br" target="_blank">Central de Ajuda</a>.<br/> Quer pagar menos taxas? <a href="//r-martins.github.io/PagSeguro-Magento-Transparente/pro/app.html" target="_blank"><strong>Autorize sua conta</strong></a> no modelo de aplicação e receba o módulo PRO gratuitamente no e-mail informado, com suporte a boleto e TEF.<br/>Se você tem taxas menores ainda, e desejar receber o módulo PRO com suporte a boleto e tef sem autorizar a aplicação, <a href="//r-martins.github.io/PagSeguro-Magento-Transparente/pro/" target="_blank">faça uma assinatura</a>.]]></comment>
34
  <label>PagSeguro - Ricardo Martins</label>
35
  <frontend_type>text</frontend_type>
36
  <sort_order>110</sort_order>
47
  <show_in_website>1</show_in_website>
48
  <show_in_store>0</show_in_store>
49
  <comment>E-mail da loja (conta vendedor)</comment>
50
+ <tooltip>E-mail da sua conta PagSeguro. Você deve ter uma Conta Vendedor ou Conta Empresarial.</tooltip>
51
  </merchant_email>
52
  <token translate="label">
53
  <label>Token</label>
58
  <show_in_website>1</show_in_website>
59
  <show_in_store>0</show_in_store>
60
  <comment>O token é obtido no seu painel do PagSeguro. Ao salvar esta página, ele será criptografado, aparentando ter um tamanho menor.</comment>
61
+ <tooltip>No caso de suspeita de token inválido ou de ter instalado outro módulo PagSeguro anteriormente, redigite o token e salve as configurações.</tooltip>
62
  </token>
63
  <sandbox translate="label">
64
  <label>Ambiente de testes?</label>
204
  <comment><![CDATA[Caso sua loja utilize um atributo personalizado para o campo 'Bairro' de entrega, selecione aqui.]]></comment>
205
  </address_neighborhood_attribute>
206
  </fields>
207
+ </rm_pagseguro>
208
+ <rm_pagseguro_cc module="ricardomartins_pagseguro">
209
  <label>PagSeguro - Cartão de Crédito - Ricardo Martins</label>
210
  <frontend_type>text</frontend_type>
211
  <sort_order>111</sort_order>
242
  <show_in_website>1</show_in_website>
243
  <show_in_store>0</show_in_store>
244
  </order_status>
245
+ <flag>
246
+ <label>Tamanho da bandeira do cartão</label>
247
+ <frontend_type>select</frontend_type>
248
+ <source_model>ricardomartins_pagseguro/source_ccbrand</source_model>
249
+ <sort_order>25</sort_order>
250
+ <show_in_default>1</show_in_default>
251
+ <show_in_website>1</show_in_website>
252
+ <show_in_store>1</show_in_store>
253
+ <tooltip><![CDATA[Exemplos: <br/><img src="//stc.pagseguro.uol.com.br/public/img/payment-methods-flags/42x20/visa.png" title="42x20"/><img src="//stc.pagseguro.uol.com.br/public/img/payment-methods-flags/68x30/visa.png" title="68x30"/>]]></tooltip>
254
+ </flag>
255
+ <info_brl>
256
+ <label>Exibir aviso que a transação é feita no Brasil.</label>
257
+ <frontend_type>select</frontend_type>
258
+ <source_model>adminhtml/system_config_source_yesno</source_model>
259
+ <sort_order>26</sort_order>
260
+ <show_in_default>1</show_in_default>
261
+ <show_in_website>1</show_in_website>
262
+ <show_in_store>1</show_in_store>
263
+ <comment><![CDATA[Esta informação DEVE conter em seu checkout por determinação da Visa.]]></comment>
264
+ </info_brl>
265
  <owner_dob_attribute>
266
  <label>Data de Nascimento</label>
267
  <frontend_type>select</frontend_type>
303
  <group_restriction>1</group_restriction>
304
  </depends>
305
  </customer_groups>
306
+ <show_total>
307
+ <label>Exibit valor total no seletor de parcelas</label>
308
+ <frontend_type>select</frontend_type>
309
+ <sort_order>70</sort_order>
310
+ <source_model>adminhtml/system_config_source_yesno</source_model>
311
+ <show_in_default>1</show_in_default>
312
+ <show_in_website>1</show_in_website>
313
+ <show_in_store>1</show_in_store>
314
+ <comment><![CDATA[Quando habilitado, o valor total do pedido é exibido junto com as informações de parcelamento.]]></comment>
315
+ </show_total>
316
  </fields>
317
+ </rm_pagseguro_cc>
318
  </groups>
319
  </payment>
320
  </sections>
app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/cc.phtml ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** @var RicardoMartins_PagSeguro_Block_Form_Cc $this */
3
+ $_code=$this->getMethodCode();
4
+ $_singleton = (Mage::app()->getStore()->isAdmin())?'adminhtml/session_quote':'checkout/session';
5
+ $_grandTotal = Mage::getSingleton($_singleton)->getQuote()->getGrandTotal();
6
+ $_grandTotal = (!$_grandTotal)?'null':$_grandTotal;
7
+ $_installments = Mage::getSingleton('checkout/session')->getQuote()->getPayment()->getAdditionalInformation('installment_quantity');
8
+ $_installments = (!$_installments)?'null':$_installments;
9
+
10
+ ?>
11
+ <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
12
+ <?php /*
13
+ <li>
14
+ <div class="input-box">
15
+ <label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Name on Card') ?></label>
16
+ <input type="text" title="<?php echo $this->__('Name on Card') ?>" class="input-text required-entry" id="<?php echo $_code ?>_cc_owner" name="payment[cc_owner]" value="<?php echo $this->escapeHtml($this->getInfoData('cc_owner')) ?>" />
17
+ </div>
18
+ </li>
19
+ */ ?>
20
+ <li>
21
+ <label for="<?php echo $_code ?>_cc_owner" class="required"><em>*</em><?php echo $this->__('Credit Card Owner\'s Name') ?></label>
22
+ <div class="input-box">
23
+ <input type="text" id="<?php echo $_code ?>_cc_owner" name="payment[ps_cc_owner]" title="<?php echo $this->__('Credit Card Owner\'s Name') ?>" class="input-text required-entry" value=""/>
24
+ </div>
25
+ </li>
26
+ <?php if($this->isDobVisible()):?>
27
+ <li id="<?php echo $_code ?>_cc_dob_div">
28
+ <?php $_dob = $this->getLayout()->createBlock('ricardomartins_pagseguro/form_cc_dob') ?>
29
+ <?php echo $_dob->toHtml() ?>
30
+ </li>
31
+ <?php endif ?>
32
+ <?php if(Mage::helper('ricardomartins_pagseguro')->isCpfVisible()):?>
33
+ <li id="<?php echo $_code ?>_cpf_div">
34
+ <label for="<?php echo $_code ?>_cpf" class="required"><em>*</em><?php echo $this->__('Credit Card Owner\'s CPF') ?></label>
35
+ <div class="input-box">
36
+ <input type="text" id="<?php echo $_code ?>_cpf" name="payment[<?php echo $_code?>_cpf]" title="<?php echo $this->__('Credit Card Owner\'s CPF') ?>" class="input-text required-entry validate-digits" value="" maxlength="11"/>
37
+ </div>
38
+ </li>
39
+ <?php endif ?>
40
+ <li>
41
+ <label for="<?php echo $_code ?>_cc_number" class="required"><em>*</em><?php echo $this->__('Credit Card Number') ?></label>
42
+ <div class="input-box">
43
+ <input type="text" id="<?php echo $_code ?>_cc_number" name="payment[ps_cc_number]" title="<?php echo $this->__('Credit Card Number') ?>" class="input-text validate-cc-number validate-cc-type required-entry" value="" maxlength="16"/>
44
+ <?php #nao remover os campos abaixo ?>
45
+ <span id="card-brand" style="text-transform: capitalize; display: block;"></span>
46
+ <span id="card-msg" style="color: red;clear:left; display: block;"></span>
47
+ </div>
48
+ </li>
49
+ <li id="<?php echo $_code ?>_cc_type_exp_div">
50
+ <label for="<?php echo $_code ?>_expiration" class="required"><em>*</em><?php echo $this->__('Expiration Date') ?></label>
51
+ <div class="input-box">
52
+ <div class="v-fix">
53
+ <select id="<?php echo $_code ?>_expiration" name="payment[ps_cc_exp_month]" class="month validate-cc-exp required-entry">
54
+ <?php $_ccExpMonth = $this->getInfoData('ps_cc_exp_month') ?>
55
+ <?php foreach ($this->getCcMonths() as $k=>$v): ?>
56
+ <option value="<?php echo $k?$k:'' ?>"<?php if($k==$_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
57
+ <?php endforeach ?>
58
+ </select>
59
+ </div>
60
+ <div class="v-fix">
61
+ <?php $_ccExpYear = $this->getInfoData('ps_cc_exp_year') ?>
62
+ <select id="<?php echo $_code ?>_expiration_yr" name="payment[ps_cc_exp_year]" class="year required-entry">
63
+ <?php foreach ($this->getCcYears() as $k=>$v): ?>
64
+ <option value="<?php echo $k?$k:'' ?>"<?php if($k==$_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option>
65
+ <?php endforeach ?>
66
+ </select>
67
+ </div>
68
+ </div>
69
+ </li>
70
+ <li id="<?php echo $_code ?>_cc_type_cvv_div">
71
+ <label for="<?php echo $_code ?>_cc_cid" class="required"><em>*</em><?php echo $this->__('Card Verification Number') ?></label>
72
+ <div class="input-box">
73
+ <div class="v-fix">
74
+ <input type="text" title="<?php echo $this->__('Card Verification Number') ?>" class="input-text cvv required-entry validate-cc-cvn" id="<?php echo $_code ?>_cc_cid" name="payment[ps_cc_cid]" value="" maxlength="4"/>
75
+ </div>
76
+ <a href="#" class="cvv-what-is-this"><?php echo $this->__('What is this?') ?></a>
77
+ </div>
78
+ </li>
79
+ <li id="<?php echo $_code ?>_cc_installments_div">
80
+ <label for="<?php echo $_code ?>_cc_installments"><?php echo $this->__('Installments') ?></label>
81
+ <div class="input-box">
82
+ <div class="v-fix">
83
+ <select name="payment[ps_cc_installments]" id="<?php echo $_code ?>_cc_installments" class="required">
84
+ <option value="">Informe os dados do cartão para calcular</option>
85
+ </select>
86
+ </div>
87
+ </div>
88
+ </li>
89
+ <?php echo $this->getChildHtml() ?>
90
+ </ul>
91
+ <script type="text/javascript">
92
+ //<![CDATA[
93
+ if(typeof RMPagSeguroObj != "undefined"){
94
+ if(RMPagSeguroObj.config.debug){
95
+ console.info('Adicionando observer para campos de cartão...');
96
+ }
97
+ if(typeof RMPagSeguroObj.brand != "undefined"){
98
+ RMPagSeguroObj.updateBrand();
99
+ RMPagSeguroObj.getInstallments(<?php echo $_grandTotal . ',' . $_installments;?>);
100
+ }
101
+ }else{
102
+ console.error('RMPagSeguroObj não foi definido.');
103
+ }
104
+ //]]
105
+ </script>
app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/cc/dob.phtml ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Academic Free License (AFL 3.0)
8
+ * that is bundled with this package in the file LICENSE_AFL.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/afl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category design
22
+ * @package base_default
23
+ * @copyright Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)
24
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
+ */
26
+
27
+ /**
28
+ USAGE:
29
+
30
+ Simple:
31
+
32
+ <?php echo $this->getLayout()->createBlock('customer/widget_dob')
33
+ ->setDate($this->getCustomer()->getDob())
34
+ ->toHtml() ?>
35
+
36
+ For checkout/onepage/billing.phtml:
37
+
38
+ <?php echo $this->getLayout()->createBlock('customer/widget_dob')
39
+ ->setDate($this->getCustomer()->getDob())
40
+ ->setFieldIdFormat('billing:%s')
41
+ ->setFieldNameFormat('billing[%s]')
42
+ ->toHtml() ?>
43
+
44
+ NOTE: Regarding styles - if we leave it this way, we'll move it to boxes.css
45
+ Alternatively we could calculate widths automatically using block input parameters.
46
+ */
47
+
48
+ /**
49
+ * @see Mage_Customer_Block_Widget_Dob
50
+ */
51
+ ?>
52
+ <label for="<?php echo $this->getFieldId('month')?>" class="required"><em>*</em><?php echo $this->__('Date of Birth') ?></label>
53
+ <div class="input-box customer-dob ps-cc-owner-dob">
54
+ <?php
55
+ $this->setDateInput('d',
56
+ '<div class="dob-day">
57
+ <input type="text" id="' . $this->getFieldId('day') . '" name="' . $this->getFieldName('day') . '" value="' . $this->getDay() . '" title="' . $this->__('Day') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="2" />
58
+ <label for="' . $this->getFieldId('day') . '">' . $this->__('DD') . '</label>
59
+ </div>'
60
+ );
61
+
62
+ $this->setDateInput('m',
63
+ '<div class="dob-month">
64
+ <input type="text" id="' . $this->getFieldId('month') . '" name="' . $this->getFieldName('month') . '" value="' . $this->getMonth() . '" title="' . $this->__('Month') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="2"/>
65
+ <label for="' . $this->getFieldId('month') . '">' . $this->__('MM') . '</label>
66
+ </div>'
67
+ );
68
+
69
+ $this->setDateInput('y',
70
+ '<div class="dob-year">
71
+ <input type="text" id="' . $this->getFieldId('year') . '" name="' . $this->getFieldName('year') . '" value="' . $this->getYear() . '" title="' . $this->__('Year') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="4"/>
72
+ <label for="' . $this->getFieldId('year') . '">' . $this->__('YYYY') . '</label>
73
+ </div>'
74
+ );
75
+ ?>
76
+ <?php echo $this->getSortedDateInputs() ?>
77
+ <div class="dob-full" style="display:none;">
78
+ <input type="hidden" id="<?php echo $this->getFieldId('dob')?>" name="<?php echo $this->getFieldName('dob')?>" />
79
+ </div>
80
+
81
+ <div class="validation-advice" style="display:none;"></div>
82
+ </div>
83
+ <script type="text/javascript">
84
+ //<![CDATA[
85
+ var ps_cc_owner_dob = new Varien.DOB('.ps-cc-owner-dob', 'true', '<?php echo $this->getDateFormat() ?>');
86
+ //]]>
87
+ </script>
app/design/adminhtml/base/default/template/ricardomartins_pagseguro/form/directpayment.phtml CHANGED
@@ -1,19 +1,22 @@
1
  <?php
2
  $_helper = Mage::helper('ricardomartins_pagseguro');
3
  ?>
4
- <input type="hidden" name="payment[sender_hash]" id="admin_sender_hash"/>
5
  <script type="text/javascript">
6
  //<![CDATA[
7
- PagSeguroDirectPayment.setSessionId('<?php echo $_helper->getSessionId();?>');
8
- var iid = setInterval(function()
9
- {
10
- if(typeof PagSeguroDirectPayment != "undefined" && PagSeguroDirectPayment.ready){
11
- console.log('PagSeguro ready');
12
-
13
- clearInterval(iid);
14
- RMPagSeguro.updateSenderHash();
15
  }
16
- }, 4000);
17
- document.getElementById('edit_form').appendChild(document.getElementById('admin_sender_hash'));
 
 
 
 
 
 
18
  //]]>
19
  </script>
1
  <?php
2
  $_helper = Mage::helper('ricardomartins_pagseguro');
3
  ?>
 
4
  <script type="text/javascript">
5
  //<![CDATA[
6
+ var preparePagSeguro = function(){
7
+ if(typeof RMPagSeguroObj != "undefined"){
8
+ <?php if ($_helper->isDebugActive()): ?>
9
+ console.info('PagSeguro was already started.');
10
+ <?php endif; ?>
11
+ return;
 
 
12
  }
13
+ <?php if ($_helper->isDebugActive()): ?>
14
+ console.info('PagSeguro is initiating. Wait for ready message.');
15
+ <?php endif; ?>
16
+ RMPagSeguroObj = new RMPagSeguro(<?php echo $_helper->getConfigJs()?>);
17
+ console.info('PagSeguro ready');
18
+ }
19
+ preparePagSeguro();
20
+
21
  //]]>
22
  </script>
app/design/frontend/base/default/template/ricardomartins_pagseguro/form/cc.phtml CHANGED
@@ -1,6 +1,11 @@
1
  <?php
2
  /** @var RicardoMartins_PagSeguro_Block_Form_Cc $this */
3
  $_code=$this->getMethodCode();
 
 
 
 
 
4
  ?>
5
  <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
6
  <?php /*
@@ -38,8 +43,6 @@ $_code=$this->getMethodCode();
38
  <?php #nao remover os campos abaixo ?>
39
  <span id="card-brand" style="text-transform: capitalize; display: block;"></span>
40
  <span id="card-msg" style="color: red;clear:left; display: block;"></span>
41
- <input type="hidden" name="payment[ps_card_type]"/>
42
- <input type="hidden" name="payment[credit_card_token]"/>
43
  </div>
44
  </li>
45
  <li id="<?php echo $_code ?>_cc_type_exp_div">
@@ -87,11 +90,29 @@ $_code=$this->getMethodCode();
87
  <?php /* O selo do PagSeguro deve ser exibido obrigatoriamente. Você pode escolher outra imagem disponivel na pasta 'selo' */ ?>
88
  <div class="selo-pagseguro"><img src="<?php echo $this->getSkinUrl('pagseguro/selo/selo04_200x60.gif');?>" alt="Pagamento processado pelo PagSeguro"/></div>
89
  </li>
 
 
 
 
 
 
 
 
90
  </ul>
91
  <script type="text/javascript">
92
  //<![CDATA[
93
- if ('undefined' !== typeof RMPagSeguro) {
94
- RMPagSeguro.getInstallments();
 
 
 
 
95
  }
 
 
 
 
 
 
96
  //]]
97
- </script>
1
  <?php
2
  /** @var RicardoMartins_PagSeguro_Block_Form_Cc $this */
3
  $_code=$this->getMethodCode();
4
+ $_grandTotal = Mage::helper('checkout/cart')->getQuote()->getGrandTotal();
5
+ $_grandTotal = (!$_grandTotal)?'null':$_grandTotal;
6
+ $_installments = Mage::getSingleton('checkout/session')->getQuote()->getPayment()->getAdditionalInformation('installment_quantity');
7
+ $_installments = (!$_installments)?'null':$_installments;
8
+
9
  ?>
10
  <ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
11
  <?php /*
43
  <?php #nao remover os campos abaixo ?>
44
  <span id="card-brand" style="text-transform: capitalize; display: block;"></span>
45
  <span id="card-msg" style="color: red;clear:left; display: block;"></span>
 
 
46
  </div>
47
  </li>
48
  <li id="<?php echo $_code ?>_cc_type_exp_div">
90
  <?php /* O selo do PagSeguro deve ser exibido obrigatoriamente. Você pode escolher outra imagem disponivel na pasta 'selo' */ ?>
91
  <div class="selo-pagseguro"><img src="<?php echo $this->getSkinUrl('pagseguro/selo/selo04_200x60.gif');?>" alt="Pagamento processado pelo PagSeguro"/></div>
92
  </li>
93
+ <?php if ($this->helper('ricardomartins_pagseguro')->isInfoBrlActive()): ?>
94
+ <li>
95
+ <p class="info-brl">
96
+ <img src="<?php echo $this->getSkinUrl('pagseguro/selo/brflag.png'); ?>" alt="Bandeira do Brasil" style="float: left">
97
+ Esta compra está sendo feita no <strong>Brasil</strong>.
98
+ </p>
99
+ </li>
100
+ <?php endif;?>
101
  </ul>
102
  <script type="text/javascript">
103
  //<![CDATA[
104
+ // if ('undefined' !== typeof RMPagSeguro) {
105
+ // RMPagSeguro.getInstallments();
106
+ // }
107
+ if(typeof RMPagSeguroObj != "undefined"){
108
+ if(RMPagSeguroObj.config.debug){
109
+ console.info('Adicionando observer para campos de cartão...');
110
  }
111
+ RMPagSeguroObj.addCardFieldsObserver(RMPagSeguroObj);
112
+ if(typeof RMPagSeguroObj.brand != "undefined"){
113
+ RMPagSeguroObj.updateBrand();
114
+ RMPagSeguroObj.getInstallments(<?php echo $_grandTotal . ',' . $_installments;?>);
115
+ }
116
+ }
117
  //]]
118
+ </script>
app/design/frontend/base/default/template/ricardomartins_pagseguro/form/cc/dob.phtml CHANGED
@@ -54,21 +54,21 @@ NOTE: Regarding styles - if we leave it this way, we'll move it to boxes.css
54
  <?php
55
  $this->setDateInput('d',
56
  '<div class="dob-day">
57
- <input type="text" id="' . $this->getFieldId('day') . '" name="' . $this->getFieldName('day') . '" value="' . $this->getDay() . '" title="' . $this->__('Day') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' />
58
  <label for="' . $this->getFieldId('day') . '">' . $this->__('DD') . '</label>
59
  </div>'
60
  );
61
 
62
  $this->setDateInput('m',
63
  '<div class="dob-month">
64
- <input type="text" id="' . $this->getFieldId('month') . '" name="' . $this->getFieldName('month') . '" value="' . $this->getMonth() . '" title="' . $this->__('Month') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' />
65
  <label for="' . $this->getFieldId('month') . '">' . $this->__('MM') . '</label>
66
  </div>'
67
  );
68
 
69
  $this->setDateInput('y',
70
  '<div class="dob-year">
71
- <input type="text" id="' . $this->getFieldId('year') . '" name="' . $this->getFieldName('year') . '" value="' . $this->getYear() . '" title="' . $this->__('Year') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' />
72
  <label for="' . $this->getFieldId('year') . '">' . $this->__('YYYY') . '</label>
73
  </div>'
74
  );
54
  <?php
55
  $this->setDateInput('d',
56
  '<div class="dob-day">
57
+ <input type="text" id="' . $this->getFieldId('day') . '" name="' . $this->getFieldName('day') . '" value="' . $this->getDay() . '" title="' . $this->__('Day') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="2" />
58
  <label for="' . $this->getFieldId('day') . '">' . $this->__('DD') . '</label>
59
  </div>'
60
  );
61
 
62
  $this->setDateInput('m',
63
  '<div class="dob-month">
64
+ <input type="text" id="' . $this->getFieldId('month') . '" name="' . $this->getFieldName('month') . '" value="' . $this->getMonth() . '" title="' . $this->__('Month') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="2"/>
65
  <label for="' . $this->getFieldId('month') . '">' . $this->__('MM') . '</label>
66
  </div>'
67
  );
68
 
69
  $this->setDateInput('y',
70
  '<div class="dob-year">
71
+ <input type="text" id="' . $this->getFieldId('year') . '" name="' . $this->getFieldName('year') . '" value="' . $this->getYear() . '" title="' . $this->__('Year') . '" class="input-text validate-custom" ' . $this->getFieldParams() . ' maxlength="4"/>
72
  <label for="' . $this->getFieldId('year') . '">' . $this->__('YYYY') . '</label>
73
  </div>'
74
  );
app/design/frontend/base/default/template/ricardomartins_pagseguro/form/directpayment.phtml CHANGED
@@ -1,22 +1,21 @@
1
  <?php
2
  $_helper = Mage::helper('ricardomartins_pagseguro');
3
  ?>
4
- <input type="hidden" name="payment[sender_hash]"/>
5
  <script type="text/javascript">
6
  //<![CDATA[
7
  var preparePagSeguro = function(){
8
- var iid = setInterval(function()
9
- {
10
- if(typeof PagSeguroDirectPayment != "undefined" && PagSeguroDirectPayment.ready){
11
- console.log('PagSeguro ready');
 
 
 
 
 
 
 
12
 
13
- clearInterval(iid);
14
- RMPagSeguro.updateSenderHash();
15
- RMPagSeguro.addBrandObserver();
16
- RMPagSeguro.addCardFieldsObserver();
17
- RMPagSeguro.removeUnavailableBanks();
18
- }
19
- }, 4000);
20
  }
21
  preparePagSeguro();
22
 
1
  <?php
2
  $_helper = Mage::helper('ricardomartins_pagseguro');
3
  ?>
 
4
  <script type="text/javascript">
5
  //<![CDATA[
6
  var preparePagSeguro = function(){
7
+ if(typeof RMPagSeguroObj != "undefined"){
8
+ <?php if ($_helper->isDebugActive()): ?>
9
+ console.info('PagSeguro was already started.');
10
+ <?php endif; ?>
11
+ return;
12
+ }
13
+ <?php if ($_helper->isDebugActive()): ?>
14
+ console.info('PagSeguro is initiating. Wait for ready message.');
15
+ <?php endif; ?>
16
+ RMPagSeguroObj = new RMPagSeguro(<?php echo $_helper->getConfigJs()?>);
17
+ console.info('PagSeguro ready');
18
 
 
 
 
 
 
 
 
19
  }
20
  preparePagSeguro();
21
 
js/pagseguro/card.js ADDED
@@ -0,0 +1,2495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var card =
2
+ /******/ (function(modules) { // webpackBootstrap
3
+ /******/ // The module cache
4
+ /******/ var installedModules = {};
5
+
6
+ /******/ // The require function
7
+ /******/ function __webpack_require__(moduleId) {
8
+
9
+ /******/ // Check if module is in cache
10
+ /******/ if(installedModules[moduleId])
11
+ /******/ return installedModules[moduleId].exports;
12
+
13
+ /******/ // Create a new module (and put it into the cache)
14
+ /******/ var module = installedModules[moduleId] = {
15
+ /******/ exports: {},
16
+ /******/ id: moduleId,
17
+ /******/ loaded: false
18
+ /******/ };
19
+
20
+ /******/ // Execute the module function
21
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
22
+
23
+ /******/ // Flag the module as loaded
24
+ /******/ module.loaded = true;
25
+
26
+ /******/ // Return the exports of the module
27
+ /******/ return module.exports;
28
+ /******/ }
29
+
30
+
31
+ /******/ // expose the modules object (__webpack_modules__)
32
+ /******/ __webpack_require__.m = modules;
33
+
34
+ /******/ // expose the module cache
35
+ /******/ __webpack_require__.c = installedModules;
36
+
37
+ /******/ // __webpack_public_path__
38
+ /******/ __webpack_require__.p = "";
39
+
40
+ /******/ // Load entry module and return exports
41
+ /******/ return __webpack_require__(0);
42
+ /******/ })
43
+ /************************************************************************/
44
+ /******/ ([
45
+ /* 0 */
46
+ /***/ function(module, exports, __webpack_require__) {
47
+
48
+ /* WEBPACK VAR INJECTION */(function(global) {var Card, QJ, extend, payment,
49
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
50
+
51
+ __webpack_require__(1);
52
+
53
+ QJ = __webpack_require__(5);
54
+
55
+ payment = __webpack_require__(6);
56
+
57
+ extend = __webpack_require__(7);
58
+
59
+ Card = (function() {
60
+ var bindVal;
61
+
62
+ Card.prototype.initializedDataAttr = "data-jp-card-initialized";
63
+
64
+ Card.prototype.cardTemplate = '' + '<div class="jp-card-container">' + '<div class="jp-card">' + '<div class="jp-card-front">' + '<div class="jp-card-logo jp-card-elo">' + '<div class="e">e</div>' + '<div class="l">l</div>' + '<div class="o">o</div>' + '</div>' + '<div class="jp-card-logo jp-card-visa">visa</div>' + '<div class="jp-card-logo jp-card-mastercard">MasterCard</div>' + '<div class="jp-card-logo jp-card-maestro">Maestro</div>' + '<div class="jp-card-logo jp-card-amex"></div>' + '<div class="jp-card-logo jp-card-discover">discover</div>' + '<div class="jp-card-logo jp-card-dankort"><div class="dk"><div class="d"></div><div class="k"></div></div></div>' + '<div class="jp-card-lower">' + '<div class="jp-card-shiny"></div>' + '<div class="jp-card-cvc jp-card-display">{{cvc}}</div>' + '<div class="jp-card-number jp-card-display">{{number}}</div>' + '<div class="jp-card-name jp-card-display">{{name}}</div>' + '<div class="jp-card-expiry jp-card-display" data-before="{{monthYear}}" data-after="{{validDate}}">{{expiry}}</div>' + '</div>' + '</div>' + '<div class="jp-card-back">' + '<div class="jp-card-bar"></div>' + '<div class="jp-card-cvc jp-card-display">{{cvc}}</div>' + '<div class="jp-card-shiny"></div>' + '</div>' + '</div>' + '</div>';
65
+
66
+ Card.prototype.template = function(tpl, data) {
67
+ return tpl.replace(/\{\{(.*?)\}\}/g, function(match, key, str) {
68
+ return data[key];
69
+ });
70
+ };
71
+
72
+ Card.prototype.cardTypes = ['jp-card-amex', 'jp-card-dankort', 'jp-card-dinersclub', 'jp-card-discover', 'jp-card-jcb', 'jp-card-laser', 'jp-card-maestro', 'jp-card-mastercard', 'jp-card-unionpay', 'jp-card-visa', 'jp-card-visaelectron', 'jp-card-elo'];
73
+
74
+ Card.prototype.defaults = {
75
+ formatting: true,
76
+ formSelectors: {
77
+ numberInput: 'input[name="number"]',
78
+ expiryInput: 'input[name="expiry"]',
79
+ cvcInput: 'input[name="cvc"]',
80
+ nameInput: 'input[name="name"]'
81
+ },
82
+ cardSelectors: {
83
+ cardContainer: '.jp-card-container',
84
+ card: '.jp-card',
85
+ numberDisplay: '.jp-card-number',
86
+ expiryDisplay: '.jp-card-expiry',
87
+ cvcDisplay: '.jp-card-cvc',
88
+ nameDisplay: '.jp-card-name'
89
+ },
90
+ messages: {
91
+ validDate: 'valid\nthru',
92
+ monthYear: 'month/year'
93
+ },
94
+ placeholders: {
95
+ number: '&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;',
96
+ cvc: '&bull;&bull;&bull;',
97
+ expiry: '&bull;&bull;/&bull;&bull;',
98
+ name: 'Full Name'
99
+ },
100
+ masks: {
101
+ cardNumber: false
102
+ },
103
+ classes: {
104
+ valid: 'jp-card-valid',
105
+ invalid: 'jp-card-invalid'
106
+ },
107
+ debug: false
108
+ };
109
+
110
+ function Card(opts) {
111
+ this.maskCardNumber = __bind(this.maskCardNumber, this);
112
+ var toInitialize;
113
+ this.options = extend(true, this.defaults, opts);
114
+ if (!this.options.form) {
115
+ console.log("Please provide a form");
116
+ return;
117
+ }
118
+ this.$el = QJ(this.options.form);
119
+ if (!this.options.container) {
120
+ console.log("Please provide a container");
121
+ return;
122
+ }
123
+ this.$container = QJ(this.options.container);
124
+ toInitialize = QJ.isDOMElement(this.$container) ? this.$container : this.$container[0];
125
+ if (toInitialize.getAttribute(this.initializedDataAttr)) {
126
+ return;
127
+ }
128
+ toInitialize.setAttribute(this.initializedDataAttr, true);
129
+ this.render();
130
+ this.attachHandlers();
131
+ this.handleInitialPlaceholders();
132
+ }
133
+
134
+ Card.prototype.render = function() {
135
+ var $cardContainer, baseWidth, name, obj, selector, ua, _ref, _ref1;
136
+ QJ.append(this.$container, this.template(this.cardTemplate, extend({}, this.options.messages, this.options.placeholders)));
137
+ _ref = this.options.cardSelectors;
138
+ for (name in _ref) {
139
+ selector = _ref[name];
140
+ this["$" + name] = QJ.find(this.$container, selector);
141
+ }
142
+ _ref1 = this.options.formSelectors;
143
+ for (name in _ref1) {
144
+ selector = _ref1[name];
145
+ selector = this.options[name] ? this.options[name] : selector;
146
+ obj = QJ.find(this.$el, selector);
147
+ if (!obj.length && this.options.debug) {
148
+ console.error("Card can't find a " + name + " in your form.");
149
+ }
150
+ this["$" + name] = obj;
151
+ }
152
+ if (this.options.formatting) {
153
+ Payment.formatCardNumber(this.$numberInput);
154
+ Payment.formatCardCVC(this.$cvcInput);
155
+ Payment.formatCardExpiry(this.$expiryInput);
156
+ }
157
+ if (this.options.width) {
158
+ $cardContainer = QJ(this.options.cardSelectors.cardContainer)[0];
159
+ baseWidth = parseInt($cardContainer.clientWidth || window.getComputedStyle($cardContainer).width);
160
+ $cardContainer.style.transform = "scale(" + (this.options.width / baseWidth) + ")";
161
+ }
162
+ if (typeof navigator !== "undefined" && navigator !== null ? navigator.userAgent : void 0) {
163
+ ua = navigator.userAgent.toLowerCase();
164
+ if (ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1) {
165
+ QJ.addClass(this.$card, 'jp-card-safari');
166
+ }
167
+ }
168
+ if (/MSIE 10\./i.test(navigator.userAgent)) {
169
+ QJ.addClass(this.$card, 'jp-card-ie-10');
170
+ }
171
+ if (/rv:11.0/i.test(navigator.userAgent)) {
172
+ return QJ.addClass(this.$card, 'jp-card-ie-11');
173
+ }
174
+ };
175
+
176
+ Card.prototype.attachHandlers = function() {
177
+ var expiryFilters, numberInputFilters;
178
+ numberInputFilters = [this.validToggler('cardNumber')];
179
+ if (this.options.masks.cardNumber) {
180
+ numberInputFilters.push(this.maskCardNumber);
181
+ }
182
+ bindVal(this.$numberInput, this.$numberDisplay, {
183
+ fill: false,
184
+ filters: numberInputFilters
185
+ });
186
+ QJ.on(this.$numberInput, 'payment.cardType', this.handle('setCardType'));
187
+ expiryFilters = [
188
+ function(val) {
189
+ return val.replace(/(\s+)/g, '');
190
+ }
191
+ ];
192
+ expiryFilters.push(this.validToggler('cardExpiry'));
193
+ bindVal(this.$expiryInput, this.$expiryDisplay, {
194
+ join: function(text) {
195
+ if (text[0].length === 2 || text[1]) {
196
+ return "/";
197
+ } else {
198
+ return "";
199
+ }
200
+ },
201
+ filters: expiryFilters
202
+ });
203
+ bindVal(this.$cvcInput, this.$cvcDisplay, {
204
+ filters: this.validToggler('cardCVC')
205
+ });
206
+ QJ.on(this.$cvcInput, 'focus', this.handle('flipCard'));
207
+ QJ.on(this.$cvcInput, 'blur', this.handle('unflipCard'));
208
+ return bindVal(this.$nameInput, this.$nameDisplay, {
209
+ fill: false,
210
+ filters: this.validToggler('cardHolderName'),
211
+ join: ' '
212
+ });
213
+ };
214
+
215
+ Card.prototype.handleInitialPlaceholders = function() {
216
+ var el, name, selector, _ref, _results;
217
+ _ref = this.options.formSelectors;
218
+ _results = [];
219
+ for (name in _ref) {
220
+ selector = _ref[name];
221
+ el = this["$" + name];
222
+ if (QJ.val(el)) {
223
+ QJ.trigger(el, 'paste');
224
+ _results.push(setTimeout(function() {
225
+ return QJ.trigger(el, 'keyup');
226
+ }));
227
+ } else {
228
+ _results.push(void 0);
229
+ }
230
+ }
231
+ return _results;
232
+ };
233
+
234
+ Card.prototype.handle = function(fn) {
235
+ return (function(_this) {
236
+ return function(e) {
237
+ var args;
238
+ args = Array.prototype.slice.call(arguments);
239
+ args.unshift(e.target);
240
+ return _this.handlers[fn].apply(_this, args);
241
+ };
242
+ })(this);
243
+ };
244
+
245
+ Card.prototype.validToggler = function(validatorName) {
246
+ var isValid;
247
+ if (validatorName === "cardExpiry") {
248
+ isValid = function(val) {
249
+ var objVal;
250
+ objVal = Payment.fns.cardExpiryVal(val);
251
+ return Payment.fns.validateCardExpiry(objVal.month, objVal.year);
252
+ };
253
+ } else if (validatorName === "cardCVC") {
254
+ isValid = (function(_this) {
255
+ return function(val) {
256
+ return Payment.fns.validateCardCVC(val, _this.cardType);
257
+ };
258
+ })(this);
259
+ } else if (validatorName === "cardNumber") {
260
+ isValid = function(val) {
261
+ return Payment.fns.validateCardNumber(val);
262
+ };
263
+ } else if (validatorName === "cardHolderName") {
264
+ isValid = function(val) {
265
+ return val !== "";
266
+ };
267
+ }
268
+ return (function(_this) {
269
+ return function(val, $in, $out) {
270
+ var result;
271
+ result = isValid(val);
272
+ _this.toggleValidClass($in, result);
273
+ _this.toggleValidClass($out, result);
274
+ return val;
275
+ };
276
+ })(this);
277
+ };
278
+
279
+ Card.prototype.toggleValidClass = function(el, test) {
280
+ QJ.toggleClass(el, this.options.classes.valid, test);
281
+ return QJ.toggleClass(el, this.options.classes.invalid, !test);
282
+ };
283
+
284
+ Card.prototype.maskCardNumber = function(val, el, out) {
285
+ var mask, numbers;
286
+ mask = this.options.masks.cardNumber;
287
+ numbers = val.split(' ');
288
+ if (numbers.length >= 3) {
289
+ numbers.forEach(function(item, idx) {
290
+ if (idx !== numbers.length - 1) {
291
+ return numbers[idx] = numbers[idx].replace(/\d/g, mask);
292
+ }
293
+ });
294
+ return numbers.join(' ');
295
+ } else {
296
+ return val.replace(/\d/g, mask);
297
+ }
298
+ };
299
+
300
+ Card.prototype.handlers = {
301
+ setCardType: function($el, e) {
302
+ var cardType;
303
+ cardType = e.data;
304
+ if (!QJ.hasClass(this.$card, cardType)) {
305
+ QJ.removeClass(this.$card, 'jp-card-unknown');
306
+ QJ.removeClass(this.$card, this.cardTypes.join(' '));
307
+ QJ.addClass(this.$card, "jp-card-" + cardType);
308
+ QJ.toggleClass(this.$card, 'jp-card-identified', cardType !== 'unknown');
309
+ return this.cardType = cardType;
310
+ }
311
+ },
312
+ flipCard: function() {
313
+ return QJ.addClass(this.$card, 'jp-card-flipped');
314
+ },
315
+ unflipCard: function() {
316
+ return QJ.removeClass(this.$card, 'jp-card-flipped');
317
+ }
318
+ };
319
+
320
+ bindVal = function(el, out, opts) {
321
+ var joiner, o, outDefaults;
322
+ if (opts == null) {
323
+ opts = {};
324
+ }
325
+ opts.fill = opts.fill || false;
326
+ opts.filters = opts.filters || [];
327
+ if (!(opts.filters instanceof Array)) {
328
+ opts.filters = [opts.filters];
329
+ }
330
+ opts.join = opts.join || "";
331
+ if (!(typeof opts.join === "function")) {
332
+ joiner = opts.join;
333
+ opts.join = function() {
334
+ return joiner;
335
+ };
336
+ }
337
+ outDefaults = (function() {
338
+ var _i, _len, _results;
339
+ _results = [];
340
+ for (_i = 0, _len = out.length; _i < _len; _i++) {
341
+ o = out[_i];
342
+ _results.push(o.textContent);
343
+ }
344
+ return _results;
345
+ })();
346
+ QJ.on(el, 'focus', function() {
347
+ return QJ.addClass(out, 'jp-card-focused');
348
+ });
349
+ QJ.on(el, 'blur', function() {
350
+ return QJ.removeClass(out, 'jp-card-focused');
351
+ });
352
+ QJ.on(el, 'keyup change paste', function(e) {
353
+ var elem, filter, i, join, outEl, outVal, val, _i, _j, _len, _len1, _ref, _results;
354
+ val = (function() {
355
+ var _i, _len, _results;
356
+ _results = [];
357
+ for (_i = 0, _len = el.length; _i < _len; _i++) {
358
+ elem = el[_i];
359
+ _results.push(QJ.val(elem));
360
+ }
361
+ return _results;
362
+ })();
363
+ join = opts.join(val);
364
+ val = val.join(join);
365
+ if (val === join) {
366
+ val = "";
367
+ }
368
+ _ref = opts.filters;
369
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
370
+ filter = _ref[_i];
371
+ val = filter(val, el, out);
372
+ }
373
+ _results = [];
374
+ for (i = _j = 0, _len1 = out.length; _j < _len1; i = ++_j) {
375
+ outEl = out[i];
376
+ if (opts.fill) {
377
+ outVal = val + outDefaults[i].substring(val.length);
378
+ } else {
379
+ outVal = val || outDefaults[i];
380
+ }
381
+ _results.push(outEl.textContent = outVal);
382
+ }
383
+ return _results;
384
+ });
385
+ return el;
386
+ };
387
+
388
+ return Card;
389
+
390
+ })();
391
+
392
+ module.exports = Card;
393
+
394
+ global.Card = Card;
395
+
396
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
397
+
398
+ /***/ },
399
+ /* 1 */
400
+ /***/ function(module, exports, __webpack_require__) {
401
+
402
+ // style-loader: Adds some css to the DOM by adding a <style> tag
403
+
404
+ // load the styles
405
+ var content = __webpack_require__(2);
406
+ if(typeof content === 'string') content = [[module.id, content, '']];
407
+ // add the styles to the DOM
408
+ var update = __webpack_require__(4)(content, {});
409
+ if(content.locals) module.exports = content.locals;
410
+ // Hot Module Replacement
411
+ if(false) {
412
+ // When the styles change, update the <style> tags
413
+ if(!content.locals) {
414
+ module.hot.accept("!!./../../node_modules/css-loader/index.js!./../../node_modules/sass-loader/index.js!./card.scss", function() {
415
+ var newContent = require("!!./../../node_modules/css-loader/index.js!./../../node_modules/sass-loader/index.js!./card.scss");
416
+ if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
417
+ update(newContent);
418
+ });
419
+ }
420
+ // When the module is disposed, remove the <style> tags
421
+ module.hot.dispose(function() { update(); });
422
+ }
423
+
424
+ /***/ },
425
+ /* 2 */
426
+ /***/ function(module, exports, __webpack_require__) {
427
+
428
+ exports = module.exports = __webpack_require__(3)();
429
+ // imports
430
+
431
+
432
+ // module
433
+ exports.push([module.id, ".jp-card.jp-card-safari.jp-card-identified .jp-card-front:before, .jp-card.jp-card-safari.jp-card-identified .jp-card-back:before {\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), -webkit-linear-gradient(-245deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%);\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), linear-gradient(-25deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%); }\n\n.jp-card.jp-card-ie-10.jp-card-flipped, .jp-card.jp-card-ie-11.jp-card-flipped {\n -webkit-transform: 0deg;\n -moz-transform: 0deg;\n -ms-transform: 0deg;\n -o-transform: 0deg;\n transform: 0deg; }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-front, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-front {\n -webkit-transform: rotateY(0deg);\n -moz-transform: rotateY(0deg);\n -ms-transform: rotateY(0deg);\n -o-transform: rotateY(0deg);\n transform: rotateY(0deg); }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-back, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-back {\n -webkit-transform: rotateY(0deg);\n -moz-transform: rotateY(0deg);\n -ms-transform: rotateY(0deg);\n -o-transform: rotateY(0deg);\n transform: rotateY(0deg); }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-back:after, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-back:after {\n left: 18%; }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-back .jp-card-cvc, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-back .jp-card-cvc {\n -webkit-transform: rotateY(180deg);\n -moz-transform: rotateY(180deg);\n -ms-transform: rotateY(180deg);\n -o-transform: rotateY(180deg);\n transform: rotateY(180deg);\n left: 5%; }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-back .jp-card-shiny, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-back .jp-card-shiny {\n left: 84%; }\n .jp-card.jp-card-ie-10.jp-card-flipped .jp-card-back .jp-card-shiny:after, .jp-card.jp-card-ie-11.jp-card-flipped .jp-card-back .jp-card-shiny:after {\n left: -480%;\n -webkit-transform: rotateY(180deg);\n -moz-transform: rotateY(180deg);\n -ms-transform: rotateY(180deg);\n -o-transform: rotateY(180deg);\n transform: rotateY(180deg); }\n\n.jp-card.jp-card-ie-10.jp-card-amex .jp-card-back, .jp-card.jp-card-ie-11.jp-card-amex .jp-card-back {\n display: none; }\n\n.jp-card-logo {\n height: 36px;\n width: 60px;\n font-style: italic; }\n .jp-card-logo, .jp-card-logo:before, .jp-card-logo:after {\n box-sizing: border-box; }\n\n.jp-card-logo.jp-card-amex {\n text-transform: uppercase;\n font-size: 4px;\n font-weight: bold;\n color: white;\n background-image: repeating-radial-gradient(circle at center, #FFF 1px, #999 2px);\n background-image: repeating-radial-gradient(circle at center, #FFF 1px, #999 2px);\n border: 1px solid #EEE; }\n .jp-card-logo.jp-card-amex:before, .jp-card-logo.jp-card-amex:after {\n width: 28px;\n display: block;\n position: absolute;\n left: 16px; }\n .jp-card-logo.jp-card-amex:before {\n height: 28px;\n content: \"american\";\n top: 3px;\n text-align: left;\n padding-left: 2px;\n padding-top: 11px;\n background: #267AC3; }\n .jp-card-logo.jp-card-amex:after {\n content: \"express\";\n bottom: 11px;\n text-align: right;\n padding-right: 2px; }\n\n.jp-card.jp-card-amex.jp-card-flipped {\n -webkit-transform: none;\n -moz-transform: none;\n -ms-transform: none;\n -o-transform: none;\n transform: none; }\n\n.jp-card.jp-card-amex.jp-card-identified .jp-card-front:before, .jp-card.jp-card-amex.jp-card-identified .jp-card-back:before {\n background-color: #108168; }\n\n.jp-card.jp-card-amex.jp-card-identified .jp-card-front .jp-card-logo.jp-card-amex {\n opacity: 1; }\n\n.jp-card.jp-card-amex.jp-card-identified .jp-card-front .jp-card-cvc {\n visibility: visible; }\n\n.jp-card.jp-card-amex.jp-card-identified .jp-card-front:after {\n opacity: 1; }\n\n.jp-card-logo.jp-card-discover {\n background: #FF6600;\n color: #111;\n text-transform: uppercase;\n font-style: normal;\n font-weight: bold;\n font-size: 10px;\n text-align: center;\n overflow: hidden;\n z-index: 1;\n padding-top: 9px;\n letter-spacing: .03em;\n border: 1px solid #EEE; }\n .jp-card-logo.jp-card-discover:before, .jp-card-logo.jp-card-discover:after {\n content: \" \";\n display: block;\n position: absolute; }\n .jp-card-logo.jp-card-discover:before {\n background: white;\n width: 200px;\n height: 200px;\n border-radius: 200px;\n bottom: -5%;\n right: -80%;\n z-index: -1; }\n .jp-card-logo.jp-card-discover:after {\n width: 8px;\n height: 8px;\n border-radius: 4px;\n top: 10px;\n left: 27px;\n background-color: #FF6600;\n background-image: -webkit-radial-gradient(#FF6600, #fff);\n background-image: radial-gradient( #FF6600, #fff);\n content: \"network\";\n font-size: 4px;\n line-height: 24px;\n text-indent: -7px; }\n\n.jp-card .jp-card-front .jp-card-logo.jp-card-discover {\n right: 12%;\n top: 18%; }\n\n.jp-card.jp-card-discover.jp-card-identified .jp-card-front:before, .jp-card.jp-card-discover.jp-card-identified .jp-card-back:before {\n background-color: #86B8CF; }\n\n.jp-card.jp-card-discover.jp-card-identified .jp-card-logo.jp-card-discover {\n opacity: 1; }\n\n.jp-card.jp-card-discover.jp-card-identified .jp-card-front:after {\n -webkit-transition: 400ms;\n -moz-transition: 400ms;\n transition: 400ms;\n content: \" \";\n display: block;\n background-color: #FF6600;\n background-image: -webkit-linear-gradient(#FF6600, #ffa366, #FF6600);\n background-image: linear-gradient(#FF6600, #ffa366, #FF6600);\n height: 50px;\n width: 50px;\n border-radius: 25px;\n position: absolute;\n left: 100%;\n top: 15%;\n margin-left: -25px;\n box-shadow: inset 1px 1px 3px 1px rgba(0, 0, 0, 0.5); }\n\n.jp-card-logo.jp-card-visa {\n background: white;\n text-transform: uppercase;\n color: #1A1876;\n text-align: center;\n font-weight: bold;\n font-size: 15px;\n line-height: 18px; }\n .jp-card-logo.jp-card-visa:before, .jp-card-logo.jp-card-visa:after {\n content: \" \";\n display: block;\n width: 100%;\n height: 25%; }\n .jp-card-logo.jp-card-visa:before {\n background: #1A1876; }\n .jp-card-logo.jp-card-visa:after {\n background: #E79800; }\n\n.jp-card.jp-card-visa.jp-card-identified .jp-card-front:before, .jp-card.jp-card-visa.jp-card-identified .jp-card-back:before {\n background-color: #191278; }\n\n.jp-card.jp-card-visa.jp-card-identified .jp-card-logo.jp-card-visa {\n opacity: 1; }\n\n.jp-card-logo.jp-card-mastercard {\n color: white;\n font-weight: bold;\n text-align: center;\n font-size: 9px;\n line-height: 36px;\n z-index: 1;\n text-shadow: 1px 1px rgba(0, 0, 0, 0.6); }\n .jp-card-logo.jp-card-mastercard:before, .jp-card-logo.jp-card-mastercard:after {\n content: \" \";\n display: block;\n width: 36px;\n top: 0;\n position: absolute;\n height: 36px;\n border-radius: 18px; }\n .jp-card-logo.jp-card-mastercard:before {\n left: 0;\n background: #FF0000;\n z-index: -1; }\n .jp-card-logo.jp-card-mastercard:after {\n right: 0;\n background: #FFAB00;\n z-index: -2; }\n\n.jp-card.jp-card-mastercard.jp-card-identified .jp-card-front .jp-card-logo.jp-card-mastercard, .jp-card.jp-card-mastercard.jp-card-identified .jp-card-back .jp-card-logo.jp-card-mastercard {\n box-shadow: none; }\n\n.jp-card.jp-card-mastercard.jp-card-identified .jp-card-front:before, .jp-card.jp-card-mastercard.jp-card-identified .jp-card-back:before {\n background-color: #0061A8; }\n\n.jp-card.jp-card-mastercard.jp-card-identified .jp-card-logo.jp-card-mastercard {\n opacity: 1; }\n\n.jp-card-logo.jp-card-maestro {\n color: white;\n font-weight: bold;\n text-align: center;\n font-size: 14px;\n line-height: 36px;\n z-index: 1;\n text-shadow: 1px 1px rgba(0, 0, 0, 0.6); }\n .jp-card-logo.jp-card-maestro:before, .jp-card-logo.jp-card-maestro:after {\n content: \" \";\n display: block;\n width: 36px;\n top: 0;\n position: absolute;\n height: 36px;\n border-radius: 18px; }\n .jp-card-logo.jp-card-maestro:before {\n left: 0;\n background: #0064CB;\n z-index: -1; }\n .jp-card-logo.jp-card-maestro:after {\n right: 0;\n background: #CC0000;\n z-index: -2; }\n\n.jp-card.jp-card-maestro.jp-card-identified .jp-card-front .jp-card-logo.jp-card-maestro, .jp-card.jp-card-maestro.jp-card-identified .jp-card-back .jp-card-logo.jp-card-maestro {\n box-shadow: none; }\n\n.jp-card.jp-card-maestro.jp-card-identified .jp-card-front:before, .jp-card.jp-card-maestro.jp-card-identified .jp-card-back:before {\n background-color: #0B2C5F; }\n\n.jp-card.jp-card-maestro.jp-card-identified .jp-card-logo.jp-card-maestro {\n opacity: 1; }\n\n.jp-card-logo.jp-card-dankort {\n width: 60px;\n height: 36px;\n padding: 3px;\n border-radius: 8px;\n border: #000000 1px solid;\n background-color: #FFFFFF; }\n .jp-card-logo.jp-card-dankort .dk {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden; }\n .jp-card-logo.jp-card-dankort .dk:before {\n background-color: #ED1C24;\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n display: block;\n border-radius: 6px; }\n .jp-card-logo.jp-card-dankort .dk:after {\n content: '';\n position: absolute;\n top: 50%;\n margin-top: -7.7px;\n right: 0;\n width: 0;\n height: 0;\n border-style: solid;\n border-width: 7px 7px 10px 0;\n border-color: transparent #ED1C24 transparent transparent;\n z-index: 1; }\n .jp-card-logo.jp-card-dankort .d, .jp-card-logo.jp-card-dankort .k {\n position: absolute;\n top: 50%;\n width: 50%;\n display: block;\n height: 15.4px;\n margin-top: -7.7px;\n background: white; }\n .jp-card-logo.jp-card-dankort .d {\n left: 0;\n border-radius: 0 8px 10px 0; }\n .jp-card-logo.jp-card-dankort .d:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n display: block;\n background: #ED1C24;\n border-radius: 2px 4px 6px 0px;\n height: 5px;\n width: 7px;\n margin: -3px 0 0 -4px; }\n .jp-card-logo.jp-card-dankort .k {\n right: 0; }\n .jp-card-logo.jp-card-dankort .k:before, .jp-card-logo.jp-card-dankort .k:after {\n content: '';\n position: absolute;\n right: 50%;\n width: 0;\n height: 0;\n border-style: solid;\n margin-right: -1px; }\n .jp-card-logo.jp-card-dankort .k:before {\n top: 0;\n border-width: 8px 5px 0 0;\n border-color: #ED1C24 transparent transparent transparent; }\n .jp-card-logo.jp-card-dankort .k:after {\n bottom: 0;\n border-width: 0 5px 8px 0;\n border-color: transparent transparent #ED1C24 transparent; }\n\n.jp-card.jp-card-dankort.jp-card-identified .jp-card-front:before, .jp-card.jp-card-dankort.jp-card-identified .jp-card-back:before {\n background-color: #0055C7; }\n\n.jp-card.jp-card-dankort.jp-card-identified .jp-card-logo.jp-card-dankort {\n opacity: 1; }\n\n.jp-card-logo.jp-card-elo {\n height: 50px;\n width: 50px;\n border-radius: 100%;\n background: black;\n color: white;\n text-align: center;\n text-transform: lowercase;\n font-size: 21px;\n font-style: normal;\n letter-spacing: 1px;\n font-weight: bold;\n padding-top: 13px; }\n .jp-card-logo.jp-card-elo .e, .jp-card-logo.jp-card-elo .l, .jp-card-logo.jp-card-elo .o {\n display: inline-block;\n position: relative; }\n .jp-card-logo.jp-card-elo .e {\n -webkit-transform: rotate(-15deg);\n -moz-transform: rotate(-15deg);\n -ms-transform: rotate(-15deg);\n -o-transform: rotate(-15deg);\n transform: rotate(-15deg); }\n .jp-card-logo.jp-card-elo .o {\n position: relative;\n display: inline-block;\n width: 12px;\n height: 12px;\n right: 0;\n top: 7px;\n border-radius: 100%;\n background-image: -webkit-linear-gradient( yellow 50%, red 50%);\n background-image: linear-gradient( yellow 50%, red 50%);\n -webkit-transform: rotate(40deg);\n -moz-transform: rotate(40deg);\n -ms-transform: rotate(40deg);\n -o-transform: rotate(40deg);\n transform: rotate(40deg);\n text-indent: -9999px; }\n .jp-card-logo.jp-card-elo .o:before {\n content: \"\";\n position: absolute;\n width: 49%;\n height: 49%;\n background: black;\n border-radius: 100%;\n text-indent: -99999px;\n top: 25%;\n left: 25%; }\n\n.jp-card.jp-card-elo.jp-card-identified .jp-card-front:before, .jp-card.jp-card-elo.jp-card-identified .jp-card-back:before {\n background-color: #6F6969; }\n\n.jp-card.jp-card-elo.jp-card-identified .jp-card-logo.jp-card-elo {\n opacity: 1; }\n\n.jp-card-container {\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n width: 350px;\n max-width: 100%;\n height: 200px;\n margin: auto;\n z-index: 1;\n position: relative; }\n\n.jp-card {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n line-height: 1;\n position: relative;\n width: 100%;\n height: 100%;\n min-width: 315px;\n border-radius: 10px;\n -webkit-transform-style: preserve-3d;\n -moz-transform-style: preserve-3d;\n -ms-transform-style: preserve-3d;\n -o-transform-style: preserve-3d;\n transform-style: preserve-3d;\n -webkit-transition: all 400ms linear;\n -moz-transition: all 400ms linear;\n transition: all 400ms linear; }\n .jp-card > *, .jp-card > *:before, .jp-card > *:after {\n -moz-box-sizing: border-box;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n font-family: inherit; }\n .jp-card.jp-card-flipped {\n -webkit-transform: rotateY(180deg);\n -moz-transform: rotateY(180deg);\n -ms-transform: rotateY(180deg);\n -o-transform: rotateY(180deg);\n transform: rotateY(180deg);\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden; }\n .jp-card .jp-card-front, .jp-card .jp-card-back {\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-transform-style: preserve-3d;\n -moz-transform-style: preserve-3d;\n -ms-transform-style: preserve-3d;\n -o-transform-style: preserve-3d;\n transform-style: preserve-3d;\n -webkit-transition: all 400ms linear;\n -moz-transition: all 400ms linear;\n transition: all 400ms linear;\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n overflow: hidden;\n border-radius: 10px;\n background: #DDD; }\n .jp-card .jp-card-front:before, .jp-card .jp-card-back:before {\n content: \" \";\n display: block;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n opacity: 0;\n border-radius: 10px;\n -webkit-transition: all 400ms ease;\n -moz-transition: all 400ms ease;\n transition: all 400ms ease; }\n .jp-card .jp-card-front:after, .jp-card .jp-card-back:after {\n content: \" \";\n display: block; }\n .jp-card .jp-card-front .jp-card-display, .jp-card .jp-card-back .jp-card-display {\n color: white;\n font-weight: normal;\n opacity: 0.5;\n -webkit-transition: opacity 400ms linear;\n -moz-transition: opacity 400ms linear;\n transition: opacity 400ms linear; }\n .jp-card .jp-card-front .jp-card-display.jp-card-focused, .jp-card .jp-card-back .jp-card-display.jp-card-focused {\n opacity: 1;\n font-weight: 700; }\n .jp-card .jp-card-front .jp-card-cvc, .jp-card .jp-card-back .jp-card-cvc {\n font-family: \"Bitstream Vera Sans Mono\", Consolas, Courier, monospace;\n font-size: 14px; }\n .jp-card .jp-card-front .jp-card-shiny, .jp-card .jp-card-back .jp-card-shiny {\n width: 50px;\n height: 35px;\n border-radius: 5px;\n background: #CCC;\n position: relative; }\n .jp-card .jp-card-front .jp-card-shiny:before, .jp-card .jp-card-back .jp-card-shiny:before {\n content: \" \";\n display: block;\n width: 70%;\n height: 60%;\n border-top-right-radius: 5px;\n border-bottom-right-radius: 5px;\n background: #d9d9d9;\n position: absolute;\n top: 20%; }\n .jp-card .jp-card-front .jp-card-logo {\n position: absolute;\n opacity: 0;\n right: 5%;\n top: 8%;\n -webkit-transition: 400ms;\n -moz-transition: 400ms;\n transition: 400ms; }\n .jp-card .jp-card-front .jp-card-lower {\n width: 80%;\n position: absolute;\n left: 10%;\n bottom: 30px; }\n @media only screen and (max-width: 480px) {\n .jp-card .jp-card-front .jp-card-lower {\n width: 90%;\n left: 5%; } }\n .jp-card .jp-card-front .jp-card-lower .jp-card-cvc {\n visibility: hidden;\n float: right;\n position: relative;\n bottom: 5px; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-number {\n font-family: \"Bitstream Vera Sans Mono\", Consolas, Courier, monospace;\n font-size: 24px;\n clear: both;\n margin-bottom: 30px; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-expiry {\n font-family: \"Bitstream Vera Sans Mono\", Consolas, Courier, monospace;\n letter-spacing: 0em;\n position: relative;\n float: right;\n width: 25%; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-expiry:before, .jp-card .jp-card-front .jp-card-lower .jp-card-expiry:after {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-weight: bold;\n font-size: 7px;\n white-space: pre;\n display: block;\n opacity: .5; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-expiry:before {\n content: attr(data-before);\n margin-bottom: 2px;\n font-size: 7px;\n text-transform: uppercase; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-expiry:after {\n position: absolute;\n content: attr(data-after);\n text-align: right;\n right: 100%;\n margin-right: 5px;\n margin-top: 2px;\n bottom: 0; }\n .jp-card .jp-card-front .jp-card-lower .jp-card-name {\n text-transform: uppercase;\n font-family: \"Bitstream Vera Sans Mono\", Consolas, Courier, monospace;\n font-size: 20px;\n max-height: 45px;\n position: absolute;\n bottom: 0;\n width: 190px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: horizontal;\n overflow: hidden;\n text-overflow: ellipsis; }\n .jp-card .jp-card-back {\n -webkit-transform: rotateY(180deg);\n -moz-transform: rotateY(180deg);\n -ms-transform: rotateY(180deg);\n -o-transform: rotateY(180deg);\n transform: rotateY(180deg); }\n .jp-card .jp-card-back .jp-card-bar {\n background-color: #444;\n background-image: -webkit-linear-gradient(#444, #333);\n background-image: linear-gradient(#444, #333);\n width: 100%;\n height: 20%;\n position: absolute;\n top: 10%; }\n .jp-card .jp-card-back:after {\n content: \" \";\n display: block;\n background-color: #FFF;\n background-image: -webkit-linear-gradient(#FFF, #FFF);\n background-image: linear-gradient(#FFF, #FFF);\n width: 80%;\n height: 16%;\n position: absolute;\n top: 40%;\n left: 2%; }\n .jp-card .jp-card-back .jp-card-cvc {\n position: absolute;\n top: 40%;\n left: 85%;\n -webkit-transition-delay: 600ms;\n -moz-transition-delay: 600ms;\n transition-delay: 600ms; }\n .jp-card .jp-card-back .jp-card-shiny {\n position: absolute;\n top: 66%;\n left: 2%; }\n .jp-card .jp-card-back .jp-card-shiny:after {\n content: \"This card has been issued by Jesse Pollak and is licensed for anyone to use anywhere for free.AIt comes with no warranty.A For support issues, please visit: github.com/jessepollak/card.\";\n position: absolute;\n left: 120%;\n top: 5%;\n color: white;\n font-size: 7px;\n width: 230px;\n opacity: .5; }\n .jp-card.jp-card-identified {\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); }\n .jp-card.jp-card-identified .jp-card-front, .jp-card.jp-card-identified .jp-card-back {\n background-color: #000;\n background-color: rgba(0, 0, 0, 0.5); }\n .jp-card.jp-card-identified .jp-card-front:before, .jp-card.jp-card-identified .jp-card-back:before {\n -webkit-transition: all 400ms ease;\n -moz-transition: all 400ms ease;\n transition: all 400ms ease;\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 90% 20%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 15% 80%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), -webkit-linear-gradient(-245deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%);\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 90% 20%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-radial-gradient(circle at 15% 80%, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), linear-gradient(-25deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%);\n opacity: 1; }\n .jp-card.jp-card-identified .jp-card-front .jp-card-logo, .jp-card.jp-card-identified .jp-card-back .jp-card-logo {\n box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3); }\n .jp-card.jp-card-identified.no-radial-gradient .jp-card-front:before, .jp-card.jp-card-identified.no-radial-gradient .jp-card-back:before {\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), -webkit-linear-gradient(-245deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%);\n background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 1px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.03) 4px), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), repeating-linear-gradient(210deg, rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0.03) 2px, rgba(255, 255, 255, 0.04) 3px, rgba(255, 255, 255, 0.05) 4px), linear-gradient(-25deg, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.2) 70%, rgba(255, 255, 255, 0) 90%); }\n", ""]);
434
+
435
+ // exports
436
+
437
+
438
+ /***/ },
439
+ /* 3 */
440
+ /***/ function(module, exports) {
441
+
442
+ /*
443
+ MIT License http://www.opensource.org/licenses/mit-license.php
444
+ Author Tobias Koppers @sokra
445
+ */
446
+ // css base code, injected by the css-loader
447
+ module.exports = function() {
448
+ var list = [];
449
+
450
+ // return the list of modules as css string
451
+ list.toString = function toString() {
452
+ var result = [];
453
+ for(var i = 0; i < this.length; i++) {
454
+ var item = this[i];
455
+ if(item[2]) {
456
+ result.push("@media " + item[2] + "{" + item[1] + "}");
457
+ } else {
458
+ result.push(item[1]);
459
+ }
460
+ }
461
+ return result.join("");
462
+ };
463
+
464
+ // import a list of modules into the list
465
+ list.i = function(modules, mediaQuery) {
466
+ if(typeof modules === "string")
467
+ modules = [[null, modules, ""]];
468
+ var alreadyImportedModules = {};
469
+ for(var i = 0; i < this.length; i++) {
470
+ var id = this[i][0];
471
+ if(typeof id === "number")
472
+ alreadyImportedModules[id] = true;
473
+ }
474
+ for(i = 0; i < modules.length; i++) {
475
+ var item = modules[i];
476
+ // skip already imported module
477
+ // this implementation is not 100% perfect for weird media query combinations
478
+ // when a module is imported multiple times with different media queries.
479
+ // I hope this will never occur (Hey this way we have smaller bundles)
480
+ if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
481
+ if(mediaQuery && !item[2]) {
482
+ item[2] = mediaQuery;
483
+ } else if(mediaQuery) {
484
+ item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
485
+ }
486
+ list.push(item);
487
+ }
488
+ }
489
+ };
490
+ return list;
491
+ };
492
+
493
+
494
+ /***/ },
495
+ /* 4 */
496
+ /***/ function(module, exports, __webpack_require__) {
497
+
498
+ /*
499
+ MIT License http://www.opensource.org/licenses/mit-license.php
500
+ Author Tobias Koppers @sokra
501
+ */
502
+ var stylesInDom = {},
503
+ memoize = function(fn) {
504
+ var memo;
505
+ return function () {
506
+ if (typeof memo === "undefined") memo = fn.apply(this, arguments);
507
+ return memo;
508
+ };
509
+ },
510
+ isOldIE = memoize(function() {
511
+ return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
512
+ }),
513
+ getHeadElement = memoize(function () {
514
+ return document.head || document.getElementsByTagName("head")[0];
515
+ }),
516
+ singletonElement = null,
517
+ singletonCounter = 0,
518
+ styleElementsInsertedAtTop = [];
519
+
520
+ module.exports = function(list, options) {
521
+ if(false) {
522
+ if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
523
+ }
524
+
525
+ options = options || {};
526
+ // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
527
+ // tags it will allow on a page
528
+ if (typeof options.singleton === "undefined") options.singleton = isOldIE();
529
+
530
+ // By default, add <style> tags to the bottom of <head>.
531
+ if (typeof options.insertAt === "undefined") options.insertAt = "bottom";
532
+
533
+ var styles = listToStyles(list);
534
+ addStylesToDom(styles, options);
535
+
536
+ return function update(newList) {
537
+ var mayRemove = [];
538
+ for(var i = 0; i < styles.length; i++) {
539
+ var item = styles[i];
540
+ var domStyle = stylesInDom[item.id];
541
+ domStyle.refs--;
542
+ mayRemove.push(domStyle);
543
+ }
544
+ if(newList) {
545
+ var newStyles = listToStyles(newList);
546
+ addStylesToDom(newStyles, options);
547
+ }
548
+ for(var i = 0; i < mayRemove.length; i++) {
549
+ var domStyle = mayRemove[i];
550
+ if(domStyle.refs === 0) {
551
+ for(var j = 0; j < domStyle.parts.length; j++)
552
+ domStyle.parts[j]();
553
+ delete stylesInDom[domStyle.id];
554
+ }
555
+ }
556
+ };
557
+ }
558
+
559
+ function addStylesToDom(styles, options) {
560
+ for(var i = 0; i < styles.length; i++) {
561
+ var item = styles[i];
562
+ var domStyle = stylesInDom[item.id];
563
+ if(domStyle) {
564
+ domStyle.refs++;
565
+ for(var j = 0; j < domStyle.parts.length; j++) {
566
+ domStyle.parts[j](item.parts[j]);
567
+ }
568
+ for(; j < item.parts.length; j++) {
569
+ domStyle.parts.push(addStyle(item.parts[j], options));
570
+ }
571
+ } else {
572
+ var parts = [];
573
+ for(var j = 0; j < item.parts.length; j++) {
574
+ parts.push(addStyle(item.parts[j], options));
575
+ }
576
+ stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
577
+ }
578
+ }
579
+ }
580
+
581
+ function listToStyles(list) {
582
+ var styles = [];
583
+ var newStyles = {};
584
+ for(var i = 0; i < list.length; i++) {
585
+ var item = list[i];
586
+ var id = item[0];
587
+ var css = item[1];
588
+ var media = item[2];
589
+ var sourceMap = item[3];
590
+ var part = {css: css, media: media, sourceMap: sourceMap};
591
+ if(!newStyles[id])
592
+ styles.push(newStyles[id] = {id: id, parts: [part]});
593
+ else
594
+ newStyles[id].parts.push(part);
595
+ }
596
+ return styles;
597
+ }
598
+
599
+ function insertStyleElement(options, styleElement) {
600
+ var head = getHeadElement();
601
+ var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
602
+ if (options.insertAt === "top") {
603
+ if(!lastStyleElementInsertedAtTop) {
604
+ head.insertBefore(styleElement, head.firstChild);
605
+ } else if(lastStyleElementInsertedAtTop.nextSibling) {
606
+ head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
607
+ } else {
608
+ head.appendChild(styleElement);
609
+ }
610
+ styleElementsInsertedAtTop.push(styleElement);
611
+ } else if (options.insertAt === "bottom") {
612
+ head.appendChild(styleElement);
613
+ } else {
614
+ throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
615
+ }
616
+ }
617
+
618
+ function removeStyleElement(styleElement) {
619
+ styleElement.parentNode.removeChild(styleElement);
620
+ var idx = styleElementsInsertedAtTop.indexOf(styleElement);
621
+ if(idx >= 0) {
622
+ styleElementsInsertedAtTop.splice(idx, 1);
623
+ }
624
+ }
625
+
626
+ function createStyleElement(options) {
627
+ var styleElement = document.createElement("style");
628
+ styleElement.type = "text/css";
629
+ insertStyleElement(options, styleElement);
630
+ return styleElement;
631
+ }
632
+
633
+ function createLinkElement(options) {
634
+ var linkElement = document.createElement("link");
635
+ linkElement.rel = "stylesheet";
636
+ insertStyleElement(options, linkElement);
637
+ return linkElement;
638
+ }
639
+
640
+ function addStyle(obj, options) {
641
+ var styleElement, update, remove;
642
+
643
+ if (options.singleton) {
644
+ var styleIndex = singletonCounter++;
645
+ styleElement = singletonElement || (singletonElement = createStyleElement(options));
646
+ update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
647
+ remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
648
+ } else if(obj.sourceMap &&
649
+ typeof URL === "function" &&
650
+ typeof URL.createObjectURL === "function" &&
651
+ typeof URL.revokeObjectURL === "function" &&
652
+ typeof Blob === "function" &&
653
+ typeof btoa === "function") {
654
+ styleElement = createLinkElement(options);
655
+ update = updateLink.bind(null, styleElement);
656
+ remove = function() {
657
+ removeStyleElement(styleElement);
658
+ if(styleElement.href)
659
+ URL.revokeObjectURL(styleElement.href);
660
+ };
661
+ } else {
662
+ styleElement = createStyleElement(options);
663
+ update = applyToTag.bind(null, styleElement);
664
+ remove = function() {
665
+ removeStyleElement(styleElement);
666
+ };
667
+ }
668
+
669
+ update(obj);
670
+
671
+ return function updateStyle(newObj) {
672
+ if(newObj) {
673
+ if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap)
674
+ return;
675
+ update(obj = newObj);
676
+ } else {
677
+ remove();
678
+ }
679
+ };
680
+ }
681
+
682
+ var replaceText = (function () {
683
+ var textStore = [];
684
+
685
+ return function (index, replacement) {
686
+ textStore[index] = replacement;
687
+ return textStore.filter(Boolean).join('\n');
688
+ };
689
+ })();
690
+
691
+ function applyToSingletonTag(styleElement, index, remove, obj) {
692
+ var css = remove ? "" : obj.css;
693
+
694
+ if (styleElement.styleSheet) {
695
+ styleElement.styleSheet.cssText = replaceText(index, css);
696
+ } else {
697
+ var cssNode = document.createTextNode(css);
698
+ var childNodes = styleElement.childNodes;
699
+ if (childNodes[index]) styleElement.removeChild(childNodes[index]);
700
+ if (childNodes.length) {
701
+ styleElement.insertBefore(cssNode, childNodes[index]);
702
+ } else {
703
+ styleElement.appendChild(cssNode);
704
+ }
705
+ }
706
+ }
707
+
708
+ function applyToTag(styleElement, obj) {
709
+ var css = obj.css;
710
+ var media = obj.media;
711
+
712
+ if(media) {
713
+ styleElement.setAttribute("media", media)
714
+ }
715
+
716
+ if(styleElement.styleSheet) {
717
+ styleElement.styleSheet.cssText = css;
718
+ } else {
719
+ while(styleElement.firstChild) {
720
+ styleElement.removeChild(styleElement.firstChild);
721
+ }
722
+ styleElement.appendChild(document.createTextNode(css));
723
+ }
724
+ }
725
+
726
+ function updateLink(linkElement, obj) {
727
+ var css = obj.css;
728
+ var sourceMap = obj.sourceMap;
729
+
730
+ if(sourceMap) {
731
+ // http://stackoverflow.com/a/26603875
732
+ css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
733
+ }
734
+
735
+ var blob = new Blob([css], { type: "text/css" });
736
+
737
+ var oldSrc = linkElement.href;
738
+
739
+ linkElement.href = URL.createObjectURL(blob);
740
+
741
+ if(oldSrc)
742
+ URL.revokeObjectURL(oldSrc);
743
+ }
744
+
745
+
746
+ /***/ },
747
+ /* 5 */
748
+ /***/ function(module, exports) {
749
+
750
+ // Generated by CoffeeScript 1.10.0
751
+ (function() {
752
+ var QJ, rreturn, rtrim;
753
+
754
+ QJ = function(selector) {
755
+ if (QJ.isDOMElement(selector)) {
756
+ return selector;
757
+ }
758
+ return document.querySelectorAll(selector);
759
+ };
760
+
761
+ QJ.isDOMElement = function(el) {
762
+ return el && (el.nodeName != null);
763
+ };
764
+
765
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
766
+
767
+ QJ.trim = function(text) {
768
+ if (text === null) {
769
+ return "";
770
+ } else {
771
+ return (text + "").replace(rtrim, "");
772
+ }
773
+ };
774
+
775
+ rreturn = /\r/g;
776
+
777
+ QJ.val = function(el, val) {
778
+ var ret;
779
+ if (arguments.length > 1) {
780
+ return el.value = val;
781
+ } else {
782
+ ret = el.value;
783
+ if (typeof ret === "string") {
784
+ return ret.replace(rreturn, "");
785
+ } else {
786
+ if (ret === null) {
787
+ return "";
788
+ } else {
789
+ return ret;
790
+ }
791
+ }
792
+ }
793
+ };
794
+
795
+ QJ.preventDefault = function(eventObject) {
796
+ if (typeof eventObject.preventDefault === "function") {
797
+ eventObject.preventDefault();
798
+ return;
799
+ }
800
+ eventObject.returnValue = false;
801
+ return false;
802
+ };
803
+
804
+ QJ.normalizeEvent = function(e) {
805
+ var original;
806
+ original = e;
807
+ e = {
808
+ which: original.which != null ? original.which : void 0,
809
+ target: original.target || original.srcElement,
810
+ preventDefault: function() {
811
+ return QJ.preventDefault(original);
812
+ },
813
+ originalEvent: original,
814
+ data: original.data || original.detail
815
+ };
816
+ if (e.which == null) {
817
+ e.which = original.charCode != null ? original.charCode : original.keyCode;
818
+ }
819
+ return e;
820
+ };
821
+
822
+ QJ.on = function(element, eventName, callback) {
823
+ var el, i, j, len, len1, multEventName, originalCallback, ref;
824
+ if (element.length) {
825
+ for (i = 0, len = element.length; i < len; i++) {
826
+ el = element[i];
827
+ QJ.on(el, eventName, callback);
828
+ }
829
+ return;
830
+ }
831
+ if (eventName.match(" ")) {
832
+ ref = eventName.split(" ");
833
+ for (j = 0, len1 = ref.length; j < len1; j++) {
834
+ multEventName = ref[j];
835
+ QJ.on(element, multEventName, callback);
836
+ }
837
+ return;
838
+ }
839
+ originalCallback = callback;
840
+ callback = function(e) {
841
+ e = QJ.normalizeEvent(e);
842
+ return originalCallback(e);
843
+ };
844
+ if (element.addEventListener) {
845
+ return element.addEventListener(eventName, callback, false);
846
+ }
847
+ if (element.attachEvent) {
848
+ eventName = "on" + eventName;
849
+ return element.attachEvent(eventName, callback);
850
+ }
851
+ element['on' + eventName] = callback;
852
+ };
853
+
854
+ QJ.addClass = function(el, className) {
855
+ var e;
856
+ if (el.length) {
857
+ return (function() {
858
+ var i, len, results;
859
+ results = [];
860
+ for (i = 0, len = el.length; i < len; i++) {
861
+ e = el[i];
862
+ results.push(QJ.addClass(e, className));
863
+ }
864
+ return results;
865
+ })();
866
+ }
867
+ if (el.classList) {
868
+ return el.classList.add(className);
869
+ } else {
870
+ return el.className += ' ' + className;
871
+ }
872
+ };
873
+
874
+ QJ.hasClass = function(el, className) {
875
+ var e, hasClass, i, len;
876
+ if (el.length) {
877
+ hasClass = true;
878
+ for (i = 0, len = el.length; i < len; i++) {
879
+ e = el[i];
880
+ hasClass = hasClass && QJ.hasClass(e, className);
881
+ }
882
+ return hasClass;
883
+ }
884
+ if (el.classList) {
885
+ return el.classList.contains(className);
886
+ } else {
887
+ return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
888
+ }
889
+ };
890
+
891
+ QJ.removeClass = function(el, className) {
892
+ var cls, e, i, len, ref, results;
893
+ if (el.length) {
894
+ return (function() {
895
+ var i, len, results;
896
+ results = [];
897
+ for (i = 0, len = el.length; i < len; i++) {
898
+ e = el[i];
899
+ results.push(QJ.removeClass(e, className));
900
+ }
901
+ return results;
902
+ })();
903
+ }
904
+ if (el.classList) {
905
+ ref = className.split(' ');
906
+ results = [];
907
+ for (i = 0, len = ref.length; i < len; i++) {
908
+ cls = ref[i];
909
+ results.push(el.classList.remove(cls));
910
+ }
911
+ return results;
912
+ } else {
913
+ return el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
914
+ }
915
+ };
916
+
917
+ QJ.toggleClass = function(el, className, bool) {
918
+ var e;
919
+ if (el.length) {
920
+ return (function() {
921
+ var i, len, results;
922
+ results = [];
923
+ for (i = 0, len = el.length; i < len; i++) {
924
+ e = el[i];
925
+ results.push(QJ.toggleClass(e, className, bool));
926
+ }
927
+ return results;
928
+ })();
929
+ }
930
+ if (bool) {
931
+ if (!QJ.hasClass(el, className)) {
932
+ return QJ.addClass(el, className);
933
+ }
934
+ } else {
935
+ return QJ.removeClass(el, className);
936
+ }
937
+ };
938
+
939
+ QJ.append = function(el, toAppend) {
940
+ var e;
941
+ if (el.length) {
942
+ return (function() {
943
+ var i, len, results;
944
+ results = [];
945
+ for (i = 0, len = el.length; i < len; i++) {
946
+ e = el[i];
947
+ results.push(QJ.append(e, toAppend));
948
+ }
949
+ return results;
950
+ })();
951
+ }
952
+ return el.insertAdjacentHTML('beforeend', toAppend);
953
+ };
954
+
955
+ QJ.find = function(el, selector) {
956
+ if (el instanceof NodeList || el instanceof Array) {
957
+ el = el[0];
958
+ }
959
+ return el.querySelectorAll(selector);
960
+ };
961
+
962
+ QJ.trigger = function(el, name, data) {
963
+ var e, error, ev;
964
+ try {
965
+ ev = new CustomEvent(name, {
966
+ detail: data
967
+ });
968
+ } catch (error) {
969
+ e = error;
970
+ ev = document.createEvent('CustomEvent');
971
+ if (ev.initCustomEvent) {
972
+ ev.initCustomEvent(name, true, true, data);
973
+ } else {
974
+ ev.initEvent(name, true, true, data);
975
+ }
976
+ }
977
+ return el.dispatchEvent(ev);
978
+ };
979
+
980
+ module.exports = QJ;
981
+
982
+ }).call(this);
983
+
984
+
985
+ /***/ },
986
+ /* 6 */
987
+ /***/ function(module, exports, __webpack_require__) {
988
+
989
+ /* WEBPACK VAR INJECTION */(function(global) {// Generated by CoffeeScript 1.10.0
990
+ (function() {
991
+ var Payment, QJ, cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlash, formatMonthExpiry, hasTextSelected, luhnCheck, reFormatCardNumber, restrictCVC, restrictCardNumber, restrictCombinedExpiry, restrictExpiry, restrictMonthExpiry, restrictNumeric, restrictYearExpiry, setCardType,
992
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
993
+
994
+ QJ = __webpack_require__(5);
995
+
996
+ defaultFormat = /(\d{1,4})/g;
997
+
998
+ cards = [
999
+ {
1000
+ type: 'amex',
1001
+ pattern: /^3[47]/,
1002
+ format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
1003
+ length: [15],
1004
+ cvcLength: [4],
1005
+ luhn: true
1006
+ }, {
1007
+ type: 'dankort',
1008
+ pattern: /^5019/,
1009
+ format: defaultFormat,
1010
+ length: [16],
1011
+ cvcLength: [3],
1012
+ luhn: true
1013
+ }, {
1014
+ type: 'dinersclub',
1015
+ pattern: /^(36|38|30[0-5])/,
1016
+ format: /(\d{1,4})(\d{1,6})?(\d{1,4})?/,
1017
+ length: [14],
1018
+ cvcLength: [3],
1019
+ luhn: true
1020
+ }, {
1021
+ type: 'discover',
1022
+ pattern: /^(6011|65|64[4-9]|622)/,
1023
+ format: defaultFormat,
1024
+ length: [16],
1025
+ cvcLength: [3],
1026
+ luhn: true
1027
+ }, {
1028
+ type: 'jcb',
1029
+ pattern: /^35/,
1030
+ format: defaultFormat,
1031
+ length: [16],
1032
+ cvcLength: [3],
1033
+ luhn: true
1034
+ }, {
1035
+ type: 'laser',
1036
+ pattern: /^(6706|6771|6709)/,
1037
+ format: defaultFormat,
1038
+ length: [16, 17, 18, 19],
1039
+ cvcLength: [3],
1040
+ luhn: true
1041
+ }, {
1042
+ type: 'maestro',
1043
+ pattern: /^(5018|5020|5038|6304|6703|6708|6759|676[1-3])/,
1044
+ format: defaultFormat,
1045
+ length: [12, 13, 14, 15, 16, 17, 18, 19],
1046
+ cvcLength: [3],
1047
+ luhn: true
1048
+ }, {
1049
+ type: 'mastercard',
1050
+ pattern: /^(5[1-5]|677189)|^(222[1-9]|2[3-6]\d{2}|27[0-1]\d|2720)/,
1051
+ format: defaultFormat,
1052
+ length: [16],
1053
+ cvcLength: [3],
1054
+ luhn: true
1055
+ }, {
1056
+ type: 'unionpay',
1057
+ pattern: /^62/,
1058
+ format: defaultFormat,
1059
+ length: [16, 17, 18, 19],
1060
+ cvcLength: [3],
1061
+ luhn: false
1062
+ }, {
1063
+ type: 'visaelectron',
1064
+ pattern: /^4(026|17500|405|508|844|91[37])/,
1065
+ format: defaultFormat,
1066
+ length: [16],
1067
+ cvcLength: [3],
1068
+ luhn: true
1069
+ }, {
1070
+ type: 'elo',
1071
+ pattern: /^(4011|438935|45(1416|76|7393)|50(4175|6699|67|90[4-7])|63(6297|6368))/,
1072
+ format: defaultFormat,
1073
+ length: [16],
1074
+ cvcLength: [3],
1075
+ luhn: true
1076
+ }, {
1077
+ type: 'visa',
1078
+ pattern: /^4/,
1079
+ format: defaultFormat,
1080
+ length: [13, 16, 19],
1081
+ cvcLength: [3],
1082
+ luhn: true
1083
+ }
1084
+ ];
1085
+
1086
+ cardFromNumber = function(num) {
1087
+ var card, i, len;
1088
+ num = (num + '').replace(/\D/g, '');
1089
+ for (i = 0, len = cards.length; i < len; i++) {
1090
+ card = cards[i];
1091
+ if (card.pattern.test(num)) {
1092
+ return card;
1093
+ }
1094
+ }
1095
+ };
1096
+
1097
+ cardFromType = function(type) {
1098
+ var card, i, len;
1099
+ for (i = 0, len = cards.length; i < len; i++) {
1100
+ card = cards[i];
1101
+ if (card.type === type) {
1102
+ return card;
1103
+ }
1104
+ }
1105
+ };
1106
+
1107
+ luhnCheck = function(num) {
1108
+ var digit, digits, i, len, odd, sum;
1109
+ odd = true;
1110
+ sum = 0;
1111
+ digits = (num + '').split('').reverse();
1112
+ for (i = 0, len = digits.length; i < len; i++) {
1113
+ digit = digits[i];
1114
+ digit = parseInt(digit, 10);
1115
+ if ((odd = !odd)) {
1116
+ digit *= 2;
1117
+ }
1118
+ if (digit > 9) {
1119
+ digit -= 9;
1120
+ }
1121
+ sum += digit;
1122
+ }
1123
+ return sum % 10 === 0;
1124
+ };
1125
+
1126
+ hasTextSelected = function(target) {
1127
+ var e, error, ref;
1128
+ try {
1129
+ if ((target.selectionStart != null) && target.selectionStart !== target.selectionEnd) {
1130
+ return true;
1131
+ }
1132
+ if ((typeof document !== "undefined" && document !== null ? (ref = document.selection) != null ? ref.createRange : void 0 : void 0) != null) {
1133
+ if (document.selection.createRange().text) {
1134
+ return true;
1135
+ }
1136
+ }
1137
+ } catch (error) {
1138
+ e = error;
1139
+ }
1140
+ return false;
1141
+ };
1142
+
1143
+ reFormatCardNumber = function(e) {
1144
+ return setTimeout((function(_this) {
1145
+ return function() {
1146
+ var target, value;
1147
+ target = e.target;
1148
+ value = QJ.val(target);
1149
+ value = Payment.fns.formatCardNumber(value);
1150
+ QJ.val(target, value);
1151
+ return QJ.trigger(target, 'change');
1152
+ };
1153
+ })(this));
1154
+ };
1155
+
1156
+ formatCardNumber = function(e) {
1157
+ var card, digit, length, re, target, upperLength, value;
1158
+ digit = String.fromCharCode(e.which);
1159
+ if (!/^\d+$/.test(digit)) {
1160
+ return;
1161
+ }
1162
+ target = e.target;
1163
+ value = QJ.val(target);
1164
+ card = cardFromNumber(value + digit);
1165
+ length = (value.replace(/\D/g, '') + digit).length;
1166
+ upperLength = 16;
1167
+ if (card) {
1168
+ upperLength = card.length[card.length.length - 1];
1169
+ }
1170
+ if (length >= upperLength) {
1171
+ return;
1172
+ }
1173
+ if (hasTextSelected(target)) {
1174
+ return;
1175
+ }
1176
+ if (card && card.type === 'amex') {
1177
+ re = /^(\d{4}|\d{4}\s\d{6})$/;
1178
+ } else {
1179
+ re = /(?:^|\s)(\d{4})$/;
1180
+ }
1181
+ if (re.test(value)) {
1182
+ e.preventDefault();
1183
+ QJ.val(target, value + ' ' + digit);
1184
+ return QJ.trigger(target, 'change');
1185
+ } else if (re.test(value + digit)) {
1186
+ e.preventDefault();
1187
+ QJ.val(target, value + digit + ' ');
1188
+ return QJ.trigger(target, 'change');
1189
+ }
1190
+ };
1191
+
1192
+ formatBackCardNumber = function(e) {
1193
+ var target, value;
1194
+ target = e.target;
1195
+ value = QJ.val(target);
1196
+ if (e.meta) {
1197
+ return;
1198
+ }
1199
+ if (e.which !== 8) {
1200
+ return;
1201
+ }
1202
+ if (hasTextSelected(target)) {
1203
+ return;
1204
+ }
1205
+ if (/\d\s$/.test(value)) {
1206
+ e.preventDefault();
1207
+ return QJ.val(target, value.replace(/\d\s$/, ''));
1208
+ } else if (/\s\d?$/.test(value)) {
1209
+ e.preventDefault();
1210
+ return QJ.val(target, value.replace(/\s\d?$/, ''));
1211
+ }
1212
+ };
1213
+
1214
+ formatExpiry = function(e) {
1215
+ var digit, target, val;
1216
+ digit = String.fromCharCode(e.which);
1217
+ if (!/^\d+$/.test(digit)) {
1218
+ return;
1219
+ }
1220
+ target = e.target;
1221
+ val = QJ.val(target) + digit;
1222
+ if (/^\d$/.test(val) && (val !== '0' && val !== '1')) {
1223
+ e.preventDefault();
1224
+ return QJ.val(target, "0" + val + " / ");
1225
+ } else if (/^\d\d$/.test(val)) {
1226
+ e.preventDefault();
1227
+ return QJ.val(target, val + " / ");
1228
+ }
1229
+ };
1230
+
1231
+ formatMonthExpiry = function(e) {
1232
+ var digit, target, val;
1233
+ digit = String.fromCharCode(e.which);
1234
+ if (!/^\d+$/.test(digit)) {
1235
+ return;
1236
+ }
1237
+ target = e.target;
1238
+ val = QJ.val(target) + digit;
1239
+ if (/^\d$/.test(val) && (val !== '0' && val !== '1')) {
1240
+ e.preventDefault();
1241
+ return QJ.val(target, "0" + val);
1242
+ } else if (/^\d\d$/.test(val)) {
1243
+ e.preventDefault();
1244
+ return QJ.val(target, "" + val);
1245
+ }
1246
+ };
1247
+
1248
+ formatForwardExpiry = function(e) {
1249
+ var digit, target, val;
1250
+ digit = String.fromCharCode(e.which);
1251
+ if (!/^\d+$/.test(digit)) {
1252
+ return;
1253
+ }
1254
+ target = e.target;
1255
+ val = QJ.val(target);
1256
+ if (/^\d\d$/.test(val)) {
1257
+ return QJ.val(target, val + " / ");
1258
+ }
1259
+ };
1260
+
1261
+ formatForwardSlash = function(e) {
1262
+ var slash, target, val;
1263
+ slash = String.fromCharCode(e.which);
1264
+ if (slash !== '/') {
1265
+ return;
1266
+ }
1267
+ target = e.target;
1268
+ val = QJ.val(target);
1269
+ if (/^\d$/.test(val) && val !== '0') {
1270
+ return QJ.val(target, "0" + val + " / ");
1271
+ }
1272
+ };
1273
+
1274
+ formatBackExpiry = function(e) {
1275
+ var target, value;
1276
+ if (e.metaKey) {
1277
+ return;
1278
+ }
1279
+ target = e.target;
1280
+ value = QJ.val(target);
1281
+ if (e.which !== 8) {
1282
+ return;
1283
+ }
1284
+ if (hasTextSelected(target)) {
1285
+ return;
1286
+ }
1287
+ if (/\d(\s|\/)+$/.test(value)) {
1288
+ e.preventDefault();
1289
+ return QJ.val(target, value.replace(/\d(\s|\/)*$/, ''));
1290
+ } else if (/\s\/\s?\d?$/.test(value)) {
1291
+ e.preventDefault();
1292
+ return QJ.val(target, value.replace(/\s\/\s?\d?$/, ''));
1293
+ }
1294
+ };
1295
+
1296
+ restrictNumeric = function(e) {
1297
+ var input;
1298
+ if (e.metaKey || e.ctrlKey) {
1299
+ return true;
1300
+ }
1301
+ if (e.which === 32) {
1302
+ return e.preventDefault();
1303
+ }
1304
+ if (e.which === 0) {
1305
+ return true;
1306
+ }
1307
+ if (e.which < 33) {
1308
+ return true;
1309
+ }
1310
+ input = String.fromCharCode(e.which);
1311
+ if (!/[\d\s]/.test(input)) {
1312
+ return e.preventDefault();
1313
+ }
1314
+ };
1315
+
1316
+ restrictCardNumber = function(e) {
1317
+ var card, digit, target, value;
1318
+ target = e.target;
1319
+ digit = String.fromCharCode(e.which);
1320
+ if (!/^\d+$/.test(digit)) {
1321
+ return;
1322
+ }
1323
+ if (hasTextSelected(target)) {
1324
+ return;
1325
+ }
1326
+ value = (QJ.val(target) + digit).replace(/\D/g, '');
1327
+ card = cardFromNumber(value);
1328
+ if (card) {
1329
+ if (!(value.length <= card.length[card.length.length - 1])) {
1330
+ return e.preventDefault();
1331
+ }
1332
+ } else {
1333
+ if (!(value.length <= 16)) {
1334
+ return e.preventDefault();
1335
+ }
1336
+ }
1337
+ };
1338
+
1339
+ restrictExpiry = function(e, length) {
1340
+ var digit, target, value;
1341
+ target = e.target;
1342
+ digit = String.fromCharCode(e.which);
1343
+ if (!/^\d+$/.test(digit)) {
1344
+ return;
1345
+ }
1346
+ if (hasTextSelected(target)) {
1347
+ return;
1348
+ }
1349
+ value = QJ.val(target) + digit;
1350
+ value = value.replace(/\D/g, '');
1351
+ if (value.length > length) {
1352
+ return e.preventDefault();
1353
+ }
1354
+ };
1355
+
1356
+ restrictCombinedExpiry = function(e) {
1357
+ return restrictExpiry(e, 6);
1358
+ };
1359
+
1360
+ restrictMonthExpiry = function(e) {
1361
+ return restrictExpiry(e, 2);
1362
+ };
1363
+
1364
+ restrictYearExpiry = function(e) {
1365
+ return restrictExpiry(e, 4);
1366
+ };
1367
+
1368
+ restrictCVC = function(e) {
1369
+ var digit, target, val;
1370
+ target = e.target;
1371
+ digit = String.fromCharCode(e.which);
1372
+ if (!/^\d+$/.test(digit)) {
1373
+ return;
1374
+ }
1375
+ if (hasTextSelected(target)) {
1376
+ return;
1377
+ }
1378
+ val = QJ.val(target) + digit;
1379
+ if (!(val.length <= 4)) {
1380
+ return e.preventDefault();
1381
+ }
1382
+ };
1383
+
1384
+ setCardType = function(e) {
1385
+ var allTypes, card, cardType, target, val;
1386
+ target = e.target;
1387
+ val = QJ.val(target);
1388
+ cardType = Payment.fns.cardType(val) || 'unknown';
1389
+ if (!QJ.hasClass(target, cardType)) {
1390
+ allTypes = (function() {
1391
+ var i, len, results;
1392
+ results = [];
1393
+ for (i = 0, len = cards.length; i < len; i++) {
1394
+ card = cards[i];
1395
+ results.push(card.type);
1396
+ }
1397
+ return results;
1398
+ })();
1399
+ QJ.removeClass(target, 'unknown');
1400
+ QJ.removeClass(target, allTypes.join(' '));
1401
+ QJ.addClass(target, cardType);
1402
+ QJ.toggleClass(target, 'identified', cardType !== 'unknown');
1403
+ return QJ.trigger(target, 'payment.cardType', cardType);
1404
+ }
1405
+ };
1406
+
1407
+ Payment = (function() {
1408
+ function Payment() {}
1409
+
1410
+ Payment.fns = {
1411
+ cardExpiryVal: function(value) {
1412
+ var month, prefix, ref, year;
1413
+ value = value.replace(/\s/g, '');
1414
+ ref = value.split('/', 2), month = ref[0], year = ref[1];
1415
+ if ((year != null ? year.length : void 0) === 2 && /^\d+$/.test(year)) {
1416
+ prefix = (new Date).getFullYear();
1417
+ prefix = prefix.toString().slice(0, 2);
1418
+ year = prefix + year;
1419
+ }
1420
+ month = parseInt(month, 10);
1421
+ year = parseInt(year, 10);
1422
+ return {
1423
+ month: month,
1424
+ year: year
1425
+ };
1426
+ },
1427
+ validateCardNumber: function(num) {
1428
+ var card, ref;
1429
+ num = (num + '').replace(/\s+|-/g, '');
1430
+ if (!/^\d+$/.test(num)) {
1431
+ return false;
1432
+ }
1433
+ card = cardFromNumber(num);
1434
+ if (!card) {
1435
+ return false;
1436
+ }
1437
+ return (ref = num.length, indexOf.call(card.length, ref) >= 0) && (card.luhn === false || luhnCheck(num));
1438
+ },
1439
+ validateCardExpiry: function(month, year) {
1440
+ var currentTime, expiry, prefix, ref, ref1;
1441
+ if (typeof month === 'object' && 'month' in month) {
1442
+ ref = month, month = ref.month, year = ref.year;
1443
+ } else if (typeof month === 'string' && indexOf.call(month, '/') >= 0) {
1444
+ ref1 = Payment.fns.cardExpiryVal(month), month = ref1.month, year = ref1.year;
1445
+ }
1446
+ if (!(month && year)) {
1447
+ return false;
1448
+ }
1449
+ month = QJ.trim(month);
1450
+ year = QJ.trim(year);
1451
+ if (!/^\d+$/.test(month)) {
1452
+ return false;
1453
+ }
1454
+ if (!/^\d+$/.test(year)) {
1455
+ return false;
1456
+ }
1457
+ month = parseInt(month, 10);
1458
+ if (!(month && month <= 12)) {
1459
+ return false;
1460
+ }
1461
+ if (year.length === 2) {
1462
+ prefix = (new Date).getFullYear();
1463
+ prefix = prefix.toString().slice(0, 2);
1464
+ year = prefix + year;
1465
+ }
1466
+ expiry = new Date(year, month);
1467
+ currentTime = new Date;
1468
+ expiry.setMonth(expiry.getMonth() - 1);
1469
+ expiry.setMonth(expiry.getMonth() + 1, 1);
1470
+ return expiry > currentTime;
1471
+ },
1472
+ validateCardCVC: function(cvc, type) {
1473
+ var ref, ref1;
1474
+ cvc = QJ.trim(cvc);
1475
+ if (!/^\d+$/.test(cvc)) {
1476
+ return false;
1477
+ }
1478
+ if (type && cardFromType(type)) {
1479
+ return ref = cvc.length, indexOf.call((ref1 = cardFromType(type)) != null ? ref1.cvcLength : void 0, ref) >= 0;
1480
+ } else {
1481
+ return cvc.length >= 3 && cvc.length <= 4;
1482
+ }
1483
+ },
1484
+ cardType: function(num) {
1485
+ var ref;
1486
+ if (!num) {
1487
+ return null;
1488
+ }
1489
+ return ((ref = cardFromNumber(num)) != null ? ref.type : void 0) || null;
1490
+ },
1491
+ formatCardNumber: function(num) {
1492
+ var card, groups, ref, upperLength;
1493
+ card = cardFromNumber(num);
1494
+ if (!card) {
1495
+ return num;
1496
+ }
1497
+ upperLength = card.length[card.length.length - 1];
1498
+ num = num.replace(/\D/g, '');
1499
+ num = num.slice(0, upperLength);
1500
+ if (card.format.global) {
1501
+ return (ref = num.match(card.format)) != null ? ref.join(' ') : void 0;
1502
+ } else {
1503
+ groups = card.format.exec(num);
1504
+ if (groups != null) {
1505
+ groups.shift();
1506
+ }
1507
+ return groups != null ? groups.join(' ') : void 0;
1508
+ }
1509
+ }
1510
+ };
1511
+
1512
+ Payment.restrictNumeric = function(el) {
1513
+ return QJ.on(el, 'keypress', restrictNumeric);
1514
+ };
1515
+
1516
+ Payment.cardExpiryVal = function(el) {
1517
+ return Payment.fns.cardExpiryVal(QJ.val(el));
1518
+ };
1519
+
1520
+ Payment.formatCardCVC = function(el) {
1521
+ Payment.restrictNumeric(el);
1522
+ QJ.on(el, 'keypress', restrictCVC);
1523
+ return el;
1524
+ };
1525
+
1526
+ Payment.formatCardExpiry = function(el) {
1527
+ var month, year;
1528
+ Payment.restrictNumeric(el);
1529
+ if (el.length && el.length === 2) {
1530
+ month = el[0], year = el[1];
1531
+ this.formatCardExpiryMultiple(month, year);
1532
+ } else {
1533
+ QJ.on(el, 'keypress', restrictCombinedExpiry);
1534
+ QJ.on(el, 'keypress', formatExpiry);
1535
+ QJ.on(el, 'keypress', formatForwardSlash);
1536
+ QJ.on(el, 'keypress', formatForwardExpiry);
1537
+ QJ.on(el, 'keydown', formatBackExpiry);
1538
+ }
1539
+ return el;
1540
+ };
1541
+
1542
+ Payment.formatCardExpiryMultiple = function(month, year) {
1543
+ QJ.on(month, 'keypress', restrictMonthExpiry);
1544
+ QJ.on(month, 'keypress', formatMonthExpiry);
1545
+ return QJ.on(year, 'keypress', restrictYearExpiry);
1546
+ };
1547
+
1548
+ Payment.formatCardNumber = function(el) {
1549
+ Payment.restrictNumeric(el);
1550
+ QJ.on(el, 'keypress', restrictCardNumber);
1551
+ QJ.on(el, 'keypress', formatCardNumber);
1552
+ QJ.on(el, 'keydown', formatBackCardNumber);
1553
+ QJ.on(el, 'keyup', setCardType);
1554
+ QJ.on(el, 'paste', reFormatCardNumber);
1555
+ return el;
1556
+ };
1557
+
1558
+ Payment.getCardArray = function() {
1559
+ return cards;
1560
+ };
1561
+
1562
+ Payment.setCardArray = function(cardArray) {
1563
+ cards = cardArray;
1564
+ return true;
1565
+ };
1566
+
1567
+ Payment.addToCardArray = function(cardObject) {
1568
+ return cards.push(cardObject);
1569
+ };
1570
+
1571
+ Payment.removeFromCardArray = function(type) {
1572
+ var key, value;
1573
+ for (key in cards) {
1574
+ value = cards[key];
1575
+ if (value.type === type) {
1576
+ cards.splice(key, 1);
1577
+ }
1578
+ }
1579
+ return true;
1580
+ };
1581
+
1582
+ return Payment;
1583
+
1584
+ })();
1585
+
1586
+ module.exports = Payment;
1587
+
1588
+ global.Payment = Payment;
1589
+
1590
+ }).call(this);
1591
+
1592
+ /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
1593
+
1594
+ /***/ },
1595
+ /* 7 */
1596
+ /***/ function(module, exports, __webpack_require__) {
1597
+
1598
+ 'use strict';
1599
+
1600
+ module.exports = __webpack_require__(8);
1601
+
1602
+
1603
+ /***/ },
1604
+ /* 8 */
1605
+ /***/ function(module, exports, __webpack_require__) {
1606
+
1607
+ 'use strict';
1608
+
1609
+ /*!
1610
+ * node.extend
1611
+ * Copyright 2011, John Resig
1612
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1613
+ * http://jquery.org/license
1614
+ *
1615
+ * @fileoverview
1616
+ * Port of jQuery.extend that actually works on node.js
1617
+ */
1618
+ var is = __webpack_require__(9);
1619
+
1620
+ var extend = function extend() {
1621
+ var target = arguments[0] || {};
1622
+ var i = 1;
1623
+ var length = arguments.length;
1624
+ var deep = false;
1625
+ var options, name, src, copy, copyIsArray, clone;
1626
+
1627
+ // Handle a deep copy situation
1628
+ if (typeof target === 'boolean') {
1629
+ deep = target;
1630
+ target = arguments[1] || {};
1631
+ // skip the boolean and the target
1632
+ i = 2;
1633
+ }
1634
+
1635
+ // Handle case when target is a string or something (possible in deep copy)
1636
+ if (typeof target !== 'object' && !is.fn(target)) {
1637
+ target = {};
1638
+ }
1639
+
1640
+ for (; i < length; i++) {
1641
+ // Only deal with non-null/undefined values
1642
+ options = arguments[i];
1643
+ if (options != null) {
1644
+ if (typeof options === 'string') {
1645
+ options = options.split('');
1646
+ }
1647
+ // Extend the base object
1648
+ for (name in options) {
1649
+ src = target[name];
1650
+ copy = options[name];
1651
+
1652
+ // Prevent never-ending loop
1653
+ if (target === copy) {
1654
+ continue;
1655
+ }
1656
+
1657
+ // Recurse if we're merging plain objects or arrays
1658
+ if (deep && copy && (is.hash(copy) || (copyIsArray = is.array(copy)))) {
1659
+ if (copyIsArray) {
1660
+ copyIsArray = false;
1661
+ clone = src && is.array(src) ? src : [];
1662
+ } else {
1663
+ clone = src && is.hash(src) ? src : {};
1664
+ }
1665
+
1666
+ // Never move original objects, clone them
1667
+ target[name] = extend(deep, clone, copy);
1668
+
1669
+ // Don't bring in undefined values
1670
+ } else if (typeof copy !== 'undefined') {
1671
+ target[name] = copy;
1672
+ }
1673
+ }
1674
+ }
1675
+ }
1676
+
1677
+ // Return the modified object
1678
+ return target;
1679
+ };
1680
+
1681
+ /**
1682
+ * @public
1683
+ */
1684
+ extend.version = '1.1.3';
1685
+
1686
+ /**
1687
+ * Exports module.
1688
+ */
1689
+ module.exports = extend;
1690
+
1691
+
1692
+ /***/ },
1693
+ /* 9 */
1694
+ /***/ function(module, exports) {
1695
+
1696
+ /* globals window, HTMLElement */
1697
+
1698
+ 'use strict';
1699
+
1700
+ /**!
1701
+ * is
1702
+ * the definitive JavaScript type testing library
1703
+ *
1704
+ * @copyright 2013-2014 Enrico Marino / Jordan Harband
1705
+ * @license MIT
1706
+ */
1707
+
1708
+ var objProto = Object.prototype;
1709
+ var owns = objProto.hasOwnProperty;
1710
+ var toStr = objProto.toString;
1711
+ var symbolValueOf;
1712
+ if (typeof Symbol === 'function') {
1713
+ symbolValueOf = Symbol.prototype.valueOf;
1714
+ }
1715
+ var isActualNaN = function (value) {
1716
+ return value !== value;
1717
+ };
1718
+ var NON_HOST_TYPES = {
1719
+ 'boolean': 1,
1720
+ number: 1,
1721
+ string: 1,
1722
+ undefined: 1
1723
+ };
1724
+
1725
+ var base64Regex = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/;
1726
+ var hexRegex = /^[A-Fa-f0-9]+$/;
1727
+
1728
+ /**
1729
+ * Expose `is`
1730
+ */
1731
+
1732
+ var is = {};
1733
+
1734
+ /**
1735
+ * Test general.
1736
+ */
1737
+
1738
+ /**
1739
+ * is.type
1740
+ * Test if `value` is a type of `type`.
1741
+ *
1742
+ * @param {Mixed} value value to test
1743
+ * @param {String} type type
1744
+ * @return {Boolean} true if `value` is a type of `type`, false otherwise
1745
+ * @api public
1746
+ */
1747
+
1748
+ is.a = is.type = function (value, type) {
1749
+ return typeof value === type;
1750
+ };
1751
+
1752
+ /**
1753
+ * is.defined
1754
+ * Test if `value` is defined.
1755
+ *
1756
+ * @param {Mixed} value value to test
1757
+ * @return {Boolean} true if 'value' is defined, false otherwise
1758
+ * @api public
1759
+ */
1760
+
1761
+ is.defined = function (value) {
1762
+ return typeof value !== 'undefined';
1763
+ };
1764
+
1765
+ /**
1766
+ * is.empty
1767
+ * Test if `value` is empty.
1768
+ *
1769
+ * @param {Mixed} value value to test
1770
+ * @return {Boolean} true if `value` is empty, false otherwise
1771
+ * @api public
1772
+ */
1773
+
1774
+ is.empty = function (value) {
1775
+ var type = toStr.call(value);
1776
+ var key;
1777
+
1778
+ if (type === '[object Array]' || type === '[object Arguments]' || type === '[object String]') {
1779
+ return value.length === 0;
1780
+ }
1781
+
1782
+ if (type === '[object Object]') {
1783
+ for (key in value) {
1784
+ if (owns.call(value, key)) {
1785
+ return false;
1786
+ }
1787
+ }
1788
+ return true;
1789
+ }
1790
+
1791
+ return !value;
1792
+ };
1793
+
1794
+ /**
1795
+ * is.equal
1796
+ * Test if `value` is equal to `other`.
1797
+ *
1798
+ * @param {Mixed} value value to test
1799
+ * @param {Mixed} other value to compare with
1800
+ * @return {Boolean} true if `value` is equal to `other`, false otherwise
1801
+ */
1802
+
1803
+ is.equal = function equal(value, other) {
1804
+ if (value === other) {
1805
+ return true;
1806
+ }
1807
+
1808
+ var type = toStr.call(value);
1809
+ var key;
1810
+
1811
+ if (type !== toStr.call(other)) {
1812
+ return false;
1813
+ }
1814
+
1815
+ if (type === '[object Object]') {
1816
+ for (key in value) {
1817
+ if (!is.equal(value[key], other[key]) || !(key in other)) {
1818
+ return false;
1819
+ }
1820
+ }
1821
+ for (key in other) {
1822
+ if (!is.equal(value[key], other[key]) || !(key in value)) {
1823
+ return false;
1824
+ }
1825
+ }
1826
+ return true;
1827
+ }
1828
+
1829
+ if (type === '[object Array]') {
1830
+ key = value.length;
1831
+ if (key !== other.length) {
1832
+ return false;
1833
+ }
1834
+ while (key--) {
1835
+ if (!is.equal(value[key], other[key])) {
1836
+ return false;
1837
+ }
1838
+ }
1839
+ return true;
1840
+ }
1841
+
1842
+ if (type === '[object Function]') {
1843
+ return value.prototype === other.prototype;
1844
+ }
1845
+
1846
+ if (type === '[object Date]') {
1847
+ return value.getTime() === other.getTime();
1848
+ }
1849
+
1850
+ return false;
1851
+ };
1852
+
1853
+ /**
1854
+ * is.hosted
1855
+ * Test if `value` is hosted by `host`.
1856
+ *
1857
+ * @param {Mixed} value to test
1858
+ * @param {Mixed} host host to test with
1859
+ * @return {Boolean} true if `value` is hosted by `host`, false otherwise
1860
+ * @api public
1861
+ */
1862
+
1863
+ is.hosted = function (value, host) {
1864
+ var type = typeof host[value];
1865
+ return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
1866
+ };
1867
+
1868
+ /**
1869
+ * is.instance
1870
+ * Test if `value` is an instance of `constructor`.
1871
+ *
1872
+ * @param {Mixed} value value to test
1873
+ * @return {Boolean} true if `value` is an instance of `constructor`
1874
+ * @api public
1875
+ */
1876
+
1877
+ is.instance = is['instanceof'] = function (value, constructor) {
1878
+ return value instanceof constructor;
1879
+ };
1880
+
1881
+ /**
1882
+ * is.nil / is.null
1883
+ * Test if `value` is null.
1884
+ *
1885
+ * @param {Mixed} value value to test
1886
+ * @return {Boolean} true if `value` is null, false otherwise
1887
+ * @api public
1888
+ */
1889
+
1890
+ is.nil = is['null'] = function (value) {
1891
+ return value === null;
1892
+ };
1893
+
1894
+ /**
1895
+ * is.undef / is.undefined
1896
+ * Test if `value` is undefined.
1897
+ *
1898
+ * @param {Mixed} value value to test
1899
+ * @return {Boolean} true if `value` is undefined, false otherwise
1900
+ * @api public
1901
+ */
1902
+
1903
+ is.undef = is.undefined = function (value) {
1904
+ return typeof value === 'undefined';
1905
+ };
1906
+
1907
+ /**
1908
+ * Test arguments.
1909
+ */
1910
+
1911
+ /**
1912
+ * is.args
1913
+ * Test if `value` is an arguments object.
1914
+ *
1915
+ * @param {Mixed} value value to test
1916
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
1917
+ * @api public
1918
+ */
1919
+
1920
+ is.args = is.arguments = function (value) {
1921
+ var isStandardArguments = toStr.call(value) === '[object Arguments]';
1922
+ var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee);
1923
+ return isStandardArguments || isOldArguments;
1924
+ };
1925
+
1926
+ /**
1927
+ * Test array.
1928
+ */
1929
+
1930
+ /**
1931
+ * is.array
1932
+ * Test if 'value' is an array.
1933
+ *
1934
+ * @param {Mixed} value value to test
1935
+ * @return {Boolean} true if `value` is an array, false otherwise
1936
+ * @api public
1937
+ */
1938
+
1939
+ is.array = Array.isArray || function (value) {
1940
+ return toStr.call(value) === '[object Array]';
1941
+ };
1942
+
1943
+ /**
1944
+ * is.arguments.empty
1945
+ * Test if `value` is an empty arguments object.
1946
+ *
1947
+ * @param {Mixed} value value to test
1948
+ * @return {Boolean} true if `value` is an empty arguments object, false otherwise
1949
+ * @api public
1950
+ */
1951
+ is.args.empty = function (value) {
1952
+ return is.args(value) && value.length === 0;
1953
+ };
1954
+
1955
+ /**
1956
+ * is.array.empty
1957
+ * Test if `value` is an empty array.
1958
+ *
1959
+ * @param {Mixed} value value to test
1960
+ * @return {Boolean} true if `value` is an empty array, false otherwise
1961
+ * @api public
1962
+ */
1963
+ is.array.empty = function (value) {
1964
+ return is.array(value) && value.length === 0;
1965
+ };
1966
+
1967
+ /**
1968
+ * is.arraylike
1969
+ * Test if `value` is an arraylike object.
1970
+ *
1971
+ * @param {Mixed} value value to test
1972
+ * @return {Boolean} true if `value` is an arguments object, false otherwise
1973
+ * @api public
1974
+ */
1975
+
1976
+ is.arraylike = function (value) {
1977
+ return !!value && !is.bool(value)
1978
+ && owns.call(value, 'length')
1979
+ && isFinite(value.length)
1980
+ && is.number(value.length)
1981
+ && value.length >= 0;
1982
+ };
1983
+
1984
+ /**
1985
+ * Test boolean.
1986
+ */
1987
+
1988
+ /**
1989
+ * is.bool
1990
+ * Test if `value` is a boolean.
1991
+ *
1992
+ * @param {Mixed} value value to test
1993
+ * @return {Boolean} true if `value` is a boolean, false otherwise
1994
+ * @api public
1995
+ */
1996
+
1997
+ is.bool = is['boolean'] = function (value) {
1998
+ return toStr.call(value) === '[object Boolean]';
1999
+ };
2000
+
2001
+ /**
2002
+ * is.false
2003
+ * Test if `value` is false.
2004
+ *
2005
+ * @param {Mixed} value value to test
2006
+ * @return {Boolean} true if `value` is false, false otherwise
2007
+ * @api public
2008
+ */
2009
+
2010
+ is['false'] = function (value) {
2011
+ return is.bool(value) && Boolean(Number(value)) === false;
2012
+ };
2013
+
2014
+ /**
2015
+ * is.true
2016
+ * Test if `value` is true.
2017
+ *
2018
+ * @param {Mixed} value value to test
2019
+ * @return {Boolean} true if `value` is true, false otherwise
2020
+ * @api public
2021
+ */
2022
+
2023
+ is['true'] = function (value) {
2024
+ return is.bool(value) && Boolean(Number(value)) === true;
2025
+ };
2026
+
2027
+ /**
2028
+ * Test date.
2029
+ */
2030
+
2031
+ /**
2032
+ * is.date
2033
+ * Test if `value` is a date.
2034
+ *
2035
+ * @param {Mixed} value value to test
2036
+ * @return {Boolean} true if `value` is a date, false otherwise
2037
+ * @api public
2038
+ */
2039
+
2040
+ is.date = function (value) {
2041
+ return toStr.call(value) === '[object Date]';
2042
+ };
2043
+
2044
+ /**
2045
+ * is.date.valid
2046
+ * Test if `value` is a valid date.
2047
+ *
2048
+ * @param {Mixed} value value to test
2049
+ * @returns {Boolean} true if `value` is a valid date, false otherwise
2050
+ */
2051
+ is.date.valid = function (value) {
2052
+ return is.date(value) && !isNaN(Number(value));
2053
+ };
2054
+
2055
+ /**
2056
+ * Test element.
2057
+ */
2058
+
2059
+ /**
2060
+ * is.element
2061
+ * Test if `value` is an html element.
2062
+ *
2063
+ * @param {Mixed} value value to test
2064
+ * @return {Boolean} true if `value` is an HTML Element, false otherwise
2065
+ * @api public
2066
+ */
2067
+
2068
+ is.element = function (value) {
2069
+ return value !== undefined
2070
+ && typeof HTMLElement !== 'undefined'
2071
+ && value instanceof HTMLElement
2072
+ && value.nodeType === 1;
2073
+ };
2074
+
2075
+ /**
2076
+ * Test error.
2077
+ */
2078
+
2079
+ /**
2080
+ * is.error
2081
+ * Test if `value` is an error object.
2082
+ *
2083
+ * @param {Mixed} value value to test
2084
+ * @return {Boolean} true if `value` is an error object, false otherwise
2085
+ * @api public
2086
+ */
2087
+
2088
+ is.error = function (value) {
2089
+ return toStr.call(value) === '[object Error]';
2090
+ };
2091
+
2092
+ /**
2093
+ * Test function.
2094
+ */
2095
+
2096
+ /**
2097
+ * is.fn / is.function (deprecated)
2098
+ * Test if `value` is a function.
2099
+ *
2100
+ * @param {Mixed} value value to test
2101
+ * @return {Boolean} true if `value` is a function, false otherwise
2102
+ * @api public
2103
+ */
2104
+
2105
+ is.fn = is['function'] = function (value) {
2106
+ var isAlert = typeof window !== 'undefined' && value === window.alert;
2107
+ return isAlert || toStr.call(value) === '[object Function]';
2108
+ };
2109
+
2110
+ /**
2111
+ * Test number.
2112
+ */
2113
+
2114
+ /**
2115
+ * is.number
2116
+ * Test if `value` is a number.
2117
+ *
2118
+ * @param {Mixed} value value to test
2119
+ * @return {Boolean} true if `value` is a number, false otherwise
2120
+ * @api public
2121
+ */
2122
+
2123
+ is.number = function (value) {
2124
+ return toStr.call(value) === '[object Number]';
2125
+ };
2126
+
2127
+ /**
2128
+ * is.infinite
2129
+ * Test if `value` is positive or negative infinity.
2130
+ *
2131
+ * @param {Mixed} value value to test
2132
+ * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise
2133
+ * @api public
2134
+ */
2135
+ is.infinite = function (value) {
2136
+ return value === Infinity || value === -Infinity;
2137
+ };
2138
+
2139
+ /**
2140
+ * is.decimal
2141
+ * Test if `value` is a decimal number.
2142
+ *
2143
+ * @param {Mixed} value value to test
2144
+ * @return {Boolean} true if `value` is a decimal number, false otherwise
2145
+ * @api public
2146
+ */
2147
+
2148
+ is.decimal = function (value) {
2149
+ return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0;
2150
+ };
2151
+
2152
+ /**
2153
+ * is.divisibleBy
2154
+ * Test if `value` is divisible by `n`.
2155
+ *
2156
+ * @param {Number} value value to test
2157
+ * @param {Number} n dividend
2158
+ * @return {Boolean} true if `value` is divisible by `n`, false otherwise
2159
+ * @api public
2160
+ */
2161
+
2162
+ is.divisibleBy = function (value, n) {
2163
+ var isDividendInfinite = is.infinite(value);
2164
+ var isDivisorInfinite = is.infinite(n);
2165
+ var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0;
2166
+ return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0);
2167
+ };
2168
+
2169
+ /**
2170
+ * is.integer
2171
+ * Test if `value` is an integer.
2172
+ *
2173
+ * @param value to test
2174
+ * @return {Boolean} true if `value` is an integer, false otherwise
2175
+ * @api public
2176
+ */
2177
+
2178
+ is.integer = is['int'] = function (value) {
2179
+ return is.number(value) && !isActualNaN(value) && value % 1 === 0;
2180
+ };
2181
+
2182
+ /**
2183
+ * is.maximum
2184
+ * Test if `value` is greater than 'others' values.
2185
+ *
2186
+ * @param {Number} value value to test
2187
+ * @param {Array} others values to compare with
2188
+ * @return {Boolean} true if `value` is greater than `others` values
2189
+ * @api public
2190
+ */
2191
+
2192
+ is.maximum = function (value, others) {
2193
+ if (isActualNaN(value)) {
2194
+ throw new TypeError('NaN is not a valid value');
2195
+ } else if (!is.arraylike(others)) {
2196
+ throw new TypeError('second argument must be array-like');
2197
+ }
2198
+ var len = others.length;
2199
+
2200
+ while (--len >= 0) {
2201
+ if (value < others[len]) {
2202
+ return false;
2203
+ }
2204
+ }
2205
+
2206
+ return true;
2207
+ };
2208
+
2209
+ /**
2210
+ * is.minimum
2211
+ * Test if `value` is less than `others` values.
2212
+ *
2213
+ * @param {Number} value value to test
2214
+ * @param {Array} others values to compare with
2215
+ * @return {Boolean} true if `value` is less than `others` values
2216
+ * @api public
2217
+ */
2218
+
2219
+ is.minimum = function (value, others) {
2220
+ if (isActualNaN(value)) {
2221
+ throw new TypeError('NaN is not a valid value');
2222
+ } else if (!is.arraylike(others)) {
2223
+ throw new TypeError('second argument must be array-like');
2224
+ }
2225
+ var len = others.length;
2226
+
2227
+ while (--len >= 0) {
2228
+ if (value > others[len]) {
2229
+ return false;
2230
+ }
2231
+ }
2232
+
2233
+ return true;
2234
+ };
2235
+
2236
+ /**
2237
+ * is.nan
2238
+ * Test if `value` is not a number.
2239
+ *
2240
+ * @param {Mixed} value value to test
2241
+ * @return {Boolean} true if `value` is not a number, false otherwise
2242
+ * @api public
2243
+ */
2244
+
2245
+ is.nan = function (value) {
2246
+ return !is.number(value) || value !== value;
2247
+ };
2248
+
2249
+ /**
2250
+ * is.even
2251
+ * Test if `value` is an even number.
2252
+ *
2253
+ * @param {Number} value value to test
2254
+ * @return {Boolean} true if `value` is an even number, false otherwise
2255
+ * @api public
2256
+ */
2257
+
2258
+ is.even = function (value) {
2259
+ return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0);
2260
+ };
2261
+
2262
+ /**
2263
+ * is.odd
2264
+ * Test if `value` is an odd number.
2265
+ *
2266
+ * @param {Number} value value to test
2267
+ * @return {Boolean} true if `value` is an odd number, false otherwise
2268
+ * @api public
2269
+ */
2270
+
2271
+ is.odd = function (value) {
2272
+ return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0);
2273
+ };
2274
+
2275
+ /**
2276
+ * is.ge
2277
+ * Test if `value` is greater than or equal to `other`.
2278
+ *
2279
+ * @param {Number} value value to test
2280
+ * @param {Number} other value to compare with
2281
+ * @return {Boolean}
2282
+ * @api public
2283
+ */
2284
+
2285
+ is.ge = function (value, other) {
2286
+ if (isActualNaN(value) || isActualNaN(other)) {
2287
+ throw new TypeError('NaN is not a valid value');
2288
+ }
2289
+ return !is.infinite(value) && !is.infinite(other) && value >= other;
2290
+ };
2291
+
2292
+ /**
2293
+ * is.gt
2294
+ * Test if `value` is greater than `other`.
2295
+ *
2296
+ * @param {Number} value value to test
2297
+ * @param {Number} other value to compare with
2298
+ * @return {Boolean}
2299
+ * @api public
2300
+ */
2301
+
2302
+ is.gt = function (value, other) {
2303
+ if (isActualNaN(value) || isActualNaN(other)) {
2304
+ throw new TypeError('NaN is not a valid value');
2305
+ }
2306
+ return !is.infinite(value) && !is.infinite(other) && value > other;
2307
+ };
2308
+
2309
+ /**
2310
+ * is.le
2311
+ * Test if `value` is less than or equal to `other`.
2312
+ *
2313
+ * @param {Number} value value to test
2314
+ * @param {Number} other value to compare with
2315
+ * @return {Boolean} if 'value' is less than or equal to 'other'
2316
+ * @api public
2317
+ */
2318
+
2319
+ is.le = function (value, other) {
2320
+ if (isActualNaN(value) || isActualNaN(other)) {
2321
+ throw new TypeError('NaN is not a valid value');
2322
+ }
2323
+ return !is.infinite(value) && !is.infinite(other) && value <= other;
2324
+ };
2325
+
2326
+ /**
2327
+ * is.lt
2328
+ * Test if `value` is less than `other`.
2329
+ *
2330
+ * @param {Number} value value to test
2331
+ * @param {Number} other value to compare with
2332
+ * @return {Boolean} if `value` is less than `other`
2333
+ * @api public
2334
+ */
2335
+
2336
+ is.lt = function (value, other) {
2337
+ if (isActualNaN(value) || isActualNaN(other)) {
2338
+ throw new TypeError('NaN is not a valid value');
2339
+ }
2340
+ return !is.infinite(value) && !is.infinite(other) && value < other;
2341
+ };
2342
+
2343
+ /**
2344
+ * is.within
2345
+ * Test if `value` is within `start` and `finish`.
2346
+ *
2347
+ * @param {Number} value value to test
2348
+ * @param {Number} start lower bound
2349
+ * @param {Number} finish upper bound
2350
+ * @return {Boolean} true if 'value' is is within 'start' and 'finish'
2351
+ * @api public
2352
+ */
2353
+ is.within = function (value, start, finish) {
2354
+ if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
2355
+ throw new TypeError('NaN is not a valid value');
2356
+ } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
2357
+ throw new TypeError('all arguments must be numbers');
2358
+ }
2359
+ var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish);
2360
+ return isAnyInfinite || (value >= start && value <= finish);
2361
+ };
2362
+
2363
+ /**
2364
+ * Test object.
2365
+ */
2366
+
2367
+ /**
2368
+ * is.object
2369
+ * Test if `value` is an object.
2370
+ *
2371
+ * @param {Mixed} value value to test
2372
+ * @return {Boolean} true if `value` is an object, false otherwise
2373
+ * @api public
2374
+ */
2375
+ is.object = function (value) {
2376
+ return toStr.call(value) === '[object Object]';
2377
+ };
2378
+
2379
+ /**
2380
+ * is.primitive
2381
+ * Test if `value` is a primitive.
2382
+ *
2383
+ * @param {Mixed} value value to test
2384
+ * @return {Boolean} true if `value` is a primitive, false otherwise
2385
+ * @api public
2386
+ */
2387
+ is.primitive = function isPrimitive(value) {
2388
+ if (!value) {
2389
+ return true;
2390
+ }
2391
+ if (typeof value === 'object' || is.object(value) || is.fn(value) || is.array(value)) {
2392
+ return false;
2393
+ }
2394
+ return true;
2395
+ };
2396
+
2397
+ /**
2398
+ * is.hash
2399
+ * Test if `value` is a hash - a plain object literal.
2400
+ *
2401
+ * @param {Mixed} value value to test
2402
+ * @return {Boolean} true if `value` is a hash, false otherwise
2403
+ * @api public
2404
+ */
2405
+
2406
+ is.hash = function (value) {
2407
+ return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
2408
+ };
2409
+
2410
+ /**
2411
+ * Test regexp.
2412
+ */
2413
+
2414
+ /**
2415
+ * is.regexp
2416
+ * Test if `value` is a regular expression.
2417
+ *
2418
+ * @param {Mixed} value value to test
2419
+ * @return {Boolean} true if `value` is a regexp, false otherwise
2420
+ * @api public
2421
+ */
2422
+
2423
+ is.regexp = function (value) {
2424
+ return toStr.call(value) === '[object RegExp]';
2425
+ };
2426
+
2427
+ /**
2428
+ * Test string.
2429
+ */
2430
+
2431
+ /**
2432
+ * is.string
2433
+ * Test if `value` is a string.
2434
+ *
2435
+ * @param {Mixed} value value to test
2436
+ * @return {Boolean} true if 'value' is a string, false otherwise
2437
+ * @api public
2438
+ */
2439
+
2440
+ is.string = function (value) {
2441
+ return toStr.call(value) === '[object String]';
2442
+ };
2443
+
2444
+ /**
2445
+ * Test base64 string.
2446
+ */
2447
+
2448
+ /**
2449
+ * is.base64
2450
+ * Test if `value` is a valid base64 encoded string.
2451
+ *
2452
+ * @param {Mixed} value value to test
2453
+ * @return {Boolean} true if 'value' is a base64 encoded string, false otherwise
2454
+ * @api public
2455
+ */
2456
+
2457
+ is.base64 = function (value) {
2458
+ return is.string(value) && (!value.length || base64Regex.test(value));
2459
+ };
2460
+
2461
+ /**
2462
+ * Test base64 string.
2463
+ */
2464
+
2465
+ /**
2466
+ * is.hex
2467
+ * Test if `value` is a valid hex encoded string.
2468
+ *
2469
+ * @param {Mixed} value value to test
2470
+ * @return {Boolean} true if 'value' is a hex encoded string, false otherwise
2471
+ * @api public
2472
+ */
2473
+
2474
+ is.hex = function (value) {
2475
+ return is.string(value) && (!value.length || hexRegex.test(value));
2476
+ };
2477
+
2478
+ /**
2479
+ * is.symbol
2480
+ * Test if `value` is an ES6 Symbol
2481
+ *
2482
+ * @param {Mixed} value value to test
2483
+ * @return {Boolean} true if `value` is a Symbol, false otherise
2484
+ * @api public
2485
+ */
2486
+
2487
+ is.symbol = function (value) {
2488
+ return typeof Symbol === 'function' && toStr.call(value) === '[object Symbol]' && typeof symbolValueOf.call(value) === 'symbol';
2489
+ };
2490
+
2491
+ module.exports = is;
2492
+
2493
+
2494
+ /***/ }
2495
+ /******/ ]);
js/pagseguro/pagseguro.js CHANGED
@@ -2,66 +2,132 @@
2
  * PagSeguro Transparente para Magento
3
  * @author Ricardo Martins <ricardo@ricardomartins.net.br>
4
  * @link https://github.com/r-martins/PagSeguro-Magento-Transparente
5
- * @version 2.5.5
6
  */
7
- (function() {
8
- document.observe("dom:loaded", function() {
9
- var errors = false;
10
- RMPagSeguro = function RMPagSeguro(){
11
- this.init = function() {
12
- this.grandTotal = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
- };
15
- RMPagSeguro.updateSenderHash = function(){
 
16
  var senderHash = PagSeguroDirectPayment.getSenderHash();
17
- if(typeof senderHash != "undefined")
18
  {
19
- if(typeof $$('input[name="payment[sender_hash]"]').first() != "undefined"){
20
- $$('input[name="payment[sender_hash]"]').first().value = senderHash;
21
- $$('input[name="payment[sender_hash]"]').first().enable();
22
- }
23
  }
24
- }
 
 
25
 
26
- RMPagSeguro.addBrandObserver = function(){
27
- var elm = $$('input[name="payment[ps_cc_number]"]').first();
28
- Event.observe(elm, 'change', function(e){
29
- var elmValue = elm.value.replace(/^\s+|\s+$/g,'');
30
- if(elmValue.length >= 6){
31
- var cBin = elmValue.substr(0,6);
32
- PagSeguroDirectPayment.getBrand({
33
- cardBin: cBin,
34
- success: function(psresponse){
35
- RMPagSeguro.brand= psresponse.brand;
36
- $('card-brand').innerHTML = psresponse.brand.name;
37
- /*Se preferir, comente a linha abaixo para exibir somente o nome do cartao. Voce tambem pode trocar 42x20 por 68x30 para obter um tamanho maior.*/
38
- $('card-brand').innerHTML = '<img src="https://stc.pagseguro.uol.com.br/public/img/payment-methods-flags/42x20/' + psresponse.brand.name + '.png" alt="' + psresponse.brand.name + '" title="' + psresponse.brand.name + '"/>';
39
- $('card-brand').className = psresponse.brand.name.replace(/[^a-zA-Z]*/g,'');
40
- $$('input[name="payment[ps_card_type]"]').first().value = psresponse.brand.name;
41
- RMPagSeguro.getInstallments();
42
- },
43
- error: function(psresponse){
44
- RMPagSeguro.brand= psresponse;
45
- $('card-brand').innerHTML = 'Cartão inválido';
 
 
 
 
 
 
 
 
 
 
46
  }
47
- });
48
- }else{
49
- $('card-brand').innerHTML = '';
50
- $('card-brand').className = '';
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
  });
53
- }
 
 
 
 
 
 
 
54
 
55
- RMPagSeguro.updateCreditCardToken = function(){
 
 
 
 
 
 
 
 
 
56
  var ccNum = $$('input[name="payment[ps_cc_number]"]').first().value.replace(/^\s+|\s+$/g,'');
57
- var ccNumElm = $$('input[name="payment[ps_cc_number]"]').first();
58
  var ccExpMo = $$('select[name="payment[ps_cc_exp_month]"]').first().value;
59
  var ccExpYr = $$('select[name="payment[ps_cc_exp_year]"]').first().value;
60
  var ccCvv = $$('input[name="payment[ps_cc_cid]"]').first().value;
61
- var ccTokenElm = $$('input[name="payment[credit_card_token]"]').first();
 
62
  var brandName = '';
63
- if(undefined != RMPagSeguro.brand){
64
- brandName = RMPagSeguro.brand.name;
65
  }
66
 
67
  if(ccNum.length > 6 && ccExpMo != "" && ccExpYr != "" && ccCvv.length >= 3)
@@ -73,7 +139,8 @@ document.observe("dom:loaded", function() {
73
  expirationMonth: ccExpMo,
74
  expirationYear: ccExpYr,
75
  success: function(psresponse){
76
- ccTokenElm.value = psresponse.card.token;
 
77
  $('card-msg').innerHTML = '';
78
  },
79
  error: function(psresponse){
@@ -86,144 +153,148 @@ document.observe("dom:loaded", function() {
86
  }else if(undefined!=psresponse.errors["30405"]){
87
  $('card-msg').innerHTML = 'Data de validade incorreta.';
88
  }else if(undefined!=psresponse.errors["30403"]){
89
- RMPagSeguro.updateSessionId(); //Se sessao expirar, atualizamos a session
90
  }else{
91
  $('card-msg').innerHTML = 'Verifique os dados do cartão digitado.';
92
  }
93
- console.log('Falha ao obter o token do cartao.');
94
  console.log(psresponse.errors);
95
  errors = true;
96
  },
97
  complete: function(psresponse){
98
- //console.log(psresponse);
99
- RMPagSeguro.reCheckSenderHash();
 
100
  }
101
  });
102
  }
103
- }
104
-
105
- RMPagSeguro.addCardFieldsObserver = function(){
106
- var ccNumElm = $$('input[name="payment[ps_cc_number]"]').first();
107
- var ccExpMoElm = $$('select[name="payment[ps_cc_exp_month]"]').first();
108
- var ccExpYrElm = $$('select[name="payment[ps_cc_exp_year]"]').first();
109
- var ccCvvElm = $$('input[name="payment[ps_cc_cid]"]').first();
110
-
111
- Element.observe(ccNumElm,'keyup',function(e){RMPagSeguro.updateCreditCardToken();});
112
- Element.observe(ccExpMoElm,'change',function(e){RMPagSeguro.updateCreditCardToken();});
113
- Element.observe(ccExpYrElm,'change',function(e){RMPagSeguro.updateCreditCardToken();});
114
- Element.observe(ccCvvElm,'keyup',function(e){RMPagSeguro.updateCreditCardToken();});
115
- }
116
 
117
- RMPagSeguro.getGrandTotal = function(){
118
- var _url = RMPagSeguroSiteBaseURL + 'pseguro/ajax/getGrandTotal';
119
- new Ajax.Request(_url, {
120
- asynchronous: false,
121
- onSuccess: function(response){
122
- RMPagSeguro.grandTotal = response.responseJSON.total;
123
- },
124
- onFailure: function(response){
125
- return false;
126
  }
127
- });
128
- }
 
 
 
 
 
129
 
130
- RMPagSeguro.getInstallments = function(){
131
- var brandName = "";
132
- if(typeof RMPagSeguro.brand == "undefined"){
133
- return;
134
- }
135
- this.getGrandTotal();
136
- if(false == RMPagSeguro.grandTotal){
137
- return 0;
 
 
 
138
  }
139
- brandName = RMPagSeguro.brand.name;
140
- PagSeguroDirectPayment.getInstallments({
141
- amount: this.grandTotal,
142
- brand: brandName,
143
- success: function(response) {
144
- var parcelsDrop = document.getElementById('pagseguro_cc_cc_installments');
145
- for( installment in response.installments) break;
146
- // console.log(response.installments);
147
- var b = response.installments[RMPagSeguro.brand.name];
148
- parcelsDrop.length = 0;
149
- for(var x=0; x < b.length; x++){
150
- var option = document.createElement('option');
151
- option.text = b[x].quantity + "x de R$" + b[x].installmentAmount.toFixed(2).toString().replace('.',',');
152
- option.text += (b[x].interestFree)?" sem juros":" com juros";
153
- option.value = b[x].quantity + "|" + b[x].installmentAmount;
154
- parcelsDrop.add(option);
155
  }
156
- // console.log(b[0].quantity);
157
- // console.log(b[0].installmentAmount);
158
-
159
  },
160
- error: function(response) {
161
- console.log(response);
162
- },
163
- complete: function(response) {
164
- // console.log(response);
165
- RMPagSeguro.reCheckSenderHash();
166
  }
167
  });
168
- }
169
-
170
- //verifica se o sender hash foi pego e tenta atualizar denvoo caso não tenha sido.
171
- RMPagSeguro.reCheckSenderHash = function()
172
- {
173
- if($$('input[name="payment[sender_hash]"]').first().value == '')
174
- {
175
- RMPagSeguro.updateSenderHash();
176
- }
177
- if($$('input[name="payment[credit_card_token]"]').first().value == '' && !errors)
178
- {
179
- RMPagSeguro.updateCreditCardToken();
180
  }
181
- }
182
-
183
- RMPagSeguro.updateSessionId = function() {
184
- var _url = RMPagSeguroSiteBaseURL + 'pseguro/ajax/getSessionId';
185
  new Ajax.Request(_url, {
186
- onSuccess: function (response) {
187
- var session_id = response.responseJSON.session_id;
188
- PagSeguroDirectPayment.setSessionId(session_id);
 
 
 
189
  }
190
  });
191
- }
192
-
193
- RMPagSeguro.removeUnavailableBanks = function(){
194
- if($('pseguro_tef_bank')){
 
 
 
195
  PagSeguroDirectPayment.getPaymentMethods({
196
- amount: RMPagSeguro.grandTotal,
197
- success: function(response){
198
- if(response.error == true){
199
  console.log('Não foi possível obter os meios de pagamento que estão funcionando no momento.');
200
  return;
201
  }
 
 
 
 
 
 
 
 
 
 
202
 
203
- try{
204
- for (y in response.paymentMethods.ONLINE_DEBIT.options){
205
- if(response.paymentMethods.ONLINE_DEBIT.options[y].status == 'UNAVAILABLE'){
206
- var valueName = response.paymentMethods.ONLINE_DEBIT.options[y].name.toString().toLowerCase();
207
- RMPagSeguro.removeOptionByValue($('pseguro_tef_bank'), valueName);
208
- console.log(response.paymentMethods.ONLINE_DEBIT.options[y].displayName + ' encontra-se indisponível e foi removido.');
209
  }
210
  }
211
- }catch (err){
 
 
 
 
212
  console.log(err.message);
213
  }
214
  }
215
  })
216
  }
217
- }
218
- RMPagSeguro.removeOptionByValue = function(selectObj, value){
219
- for (x in selectObj.options) {
220
- if(selectObj.options[x].value == value){
221
- selectObj.options[x] = null;
222
- break;
 
 
 
 
223
  }
224
- }
225
  }
226
- window.RMPagSeguro = RMPagSeguro;
227
- RMPagSeguro.updateSessionId();
228
  });
229
- }());
2
  * PagSeguro Transparente para Magento
3
  * @author Ricardo Martins <ricardo@ricardomartins.net.br>
4
  * @link https://github.com/r-martins/PagSeguro-Magento-Transparente
5
+ * @version 3.0.0
6
  */
7
+
8
+ RMPagSeguro = Class.create({
9
+ initialize: function (config) {
10
+ if (typeof config.checkoutFormElm == "undefined") {
11
+ var methods= $$('#p_method_rm_pagseguro_cc', '#p_method_pagseguropro_boleto', '#p_method_pagseguropro_tef');
12
+ if(!methods.length){
13
+ console.log('PagSeguro: Não há métodos de pagamento habilitados em exibição. Execução abortada.');
14
+ return;
15
+ }
16
+ }
17
+
18
+ if(config.PagSeguroSessionId == false){
19
+ console.error('Não foi possível obter o SessionId do PagSeguro. Verifique seu token, chave e configurações.');
20
+ }
21
+ console.log('RMPagSeguro prototype class has been initialized.');
22
+
23
+ this.config = config;
24
+
25
+ PagSeguroDirectPayment.setSessionId(config.PagSeguroSessionId);
26
+
27
+
28
+ var senderHashSuccess = this.updateSenderHash();
29
+ if(!senderHashSuccess){
30
+ console.log('Uma nova tentativa de obter o sender_hash será realizada.');
31
+ document.observe("click", function(e){
32
+ var senderHashSuccess = RMPagSeguroObj.updateSenderHash();
33
+ if(!senderHashSuccess){
34
+ console.log('PagSeguro: segunda tentativa de obter o hash do comprador (sender_hash) falhou. Tente manualmente com RMPagSeguroObj.updateSenderHash().');
35
+ return;
36
+ }
37
+ document.stopObserving('click');
38
+ });
39
  }
40
+ },
41
+
42
+ updateSenderHash: function() {
43
  var senderHash = PagSeguroDirectPayment.getSenderHash();
44
+ if(typeof senderHash != "undefined" && senderHash != '')
45
  {
46
+ this.senderHash = senderHash;
47
+ this.updatePaymentHashes();
48
+ return true;
 
49
  }
50
+ console.log('PagSeguro: Falha ao obter o senderHash.');
51
+ return false;
52
+ },
53
 
54
+ getInstallments: function(grandTotal, selectedInstallment){
55
+ var brandName = "";
56
+ if(typeof RMPagSeguroObj.brand == "undefined"){
57
+ return;
58
+ }
59
+ if(!grandTotal){
60
+ grandTotal = this.getGrandTotal();
61
+ return;
62
+ }
63
+ this.grandTotal = grandTotal;
64
+ if(!selectedInstallment){
65
+ selectedInstallment = 1;
66
+ }
67
+
68
+ brandName = RMPagSeguroObj.brand.name;
69
+ PagSeguroDirectPayment.getInstallments({
70
+ amount: grandTotal,
71
+ brand: brandName,
72
+ success: function(response) {
73
+ var parcelsDrop = $('rm_pagseguro_cc_cc_installments');
74
+ for(installment in response.installments) break;
75
+ // console.log(response.installments);
76
+ var b = response.installments[RMPagSeguroObj.brand.name];
77
+ parcelsDrop.length = 0;
78
+ for(var x=0; x < b.length; x++){
79
+ var option = document.createElement('option');
80
+ option.text = b[x].quantity + "x de R$" + b[x].installmentAmount.toFixed(2).toString().replace('.',',');
81
+ option.text += (b[x].interestFree)?" sem juros":" com juros";
82
+ if(RMPagSeguroObj.config.show_total){
83
+ option.text += " (total R$" + (b[x].installmentAmount*b[x].quantity).toFixed(2).toString().replace('.', ',') + ")";
84
  }
85
+ option.selected = (b[x].quantity == selectedInstallment);
86
+ option.value = b[x].quantity + "|" + b[x].installmentAmount;
87
+ parcelsDrop.add(option);
88
+ }
89
+ // console.log(b[0].quantity);
90
+ // console.log(b[0].installmentAmount);
91
+
92
+ },
93
+ error: function(response) {
94
+ console.error('Erro ao obter parcelas:');
95
+ console.error(response);
96
+ },
97
+ complete: function(response) {
98
+ // console.log(response);
99
+ // RMPagSeguro.reCheckSenderHash();
100
  }
101
  });
102
+ },
103
+
104
+ addCardFieldsObserver: function(obj){
105
+ try {
106
+ var ccNumElm = $$('input[name="payment[ps_cc_number]"]').first();
107
+ var ccExpMoElm = $$('select[name="payment[ps_cc_exp_month]"]').first();
108
+ var ccExpYrElm = $$('select[name="payment[ps_cc_exp_year]"]').first();
109
+ var ccCvvElm = $$('input[name="payment[ps_cc_cid]"]').first();
110
 
111
+ Element.observe(ccNumElm,'keyup',function(e){obj.updateCreditCardToken();});
112
+ Element.observe(ccExpMoElm,'change',function(e){obj.updateCreditCardToken();});
113
+ Element.observe(ccExpYrElm,'change',function(e){obj.updateCreditCardToken();});
114
+ Element.observe(ccCvvElm,'change',function(e){obj.updateCreditCardToken();});
115
+ }catch(e){
116
+ console.error('Não foi possível adicionar observevação aos cartões. ' + e.message);
117
+ }
118
+
119
+ },
120
+ updateCreditCardToken: function(){
121
  var ccNum = $$('input[name="payment[ps_cc_number]"]').first().value.replace(/^\s+|\s+$/g,'');
122
+ // var ccNumElm = $$('input[name="payment[ps_cc_number]"]').first();
123
  var ccExpMo = $$('select[name="payment[ps_cc_exp_month]"]').first().value;
124
  var ccExpYr = $$('select[name="payment[ps_cc_exp_year]"]').first().value;
125
  var ccCvv = $$('input[name="payment[ps_cc_cid]"]').first().value;
126
+
127
+ this.updateBrand();
128
  var brandName = '';
129
+ if(typeof RMPagSeguroObj.brand != "undefined"){
130
+ brandName = RMPagSeguroObj.brand.name;
131
  }
132
 
133
  if(ccNum.length > 6 && ccExpMo != "" && ccExpYr != "" && ccCvv.length >= 3)
139
  expirationMonth: ccExpMo,
140
  expirationYear: ccExpYr,
141
  success: function(psresponse){
142
+ RMPagSeguroObj.creditCardToken = psresponse.card.token;
143
+ RMPagSeguroObj.updatePaymentHashes();
144
  $('card-msg').innerHTML = '';
145
  },
146
  error: function(psresponse){
153
  }else if(undefined!=psresponse.errors["30405"]){
154
  $('card-msg').innerHTML = 'Data de validade incorreta.';
155
  }else if(undefined!=psresponse.errors["30403"]){
156
+ RMPagSeguroObj.updateSessionId(); //Se sessao expirar, atualizamos a session
157
  }else{
158
  $('card-msg').innerHTML = 'Verifique os dados do cartão digitado.';
159
  }
160
+ console.error('Falha ao obter o token do cartao.');
161
  console.log(psresponse.errors);
162
  errors = true;
163
  },
164
  complete: function(psresponse){
165
+ if(RMPagSeguroObj.config.debug){
166
+ console.info('Card token updated successfully.');
167
+ }
168
  }
169
  });
170
  }
171
+ if(typeof RMPagSeguroObj.brand != "undefined") {
172
+ this.getInstallments();
173
+ }
174
+ },
175
+ updateBrand: function(){
176
+ var ccNum = $$('input[name="payment[ps_cc_number]"]').first().value.replace(/^\s+|\s+$/g,'');
177
+ var currentBin = ccNum.substring(0, 6);
178
+ var flag = RMPagSeguroObj.config.flag;
 
 
 
 
 
179
 
180
+ if(ccNum.length >= 6){
181
+ if (typeof RMPagSeguroObj.cardBin != "undefined" && currentBin == RMPagSeguroObj.cardBin) {
182
+ if(typeof RMPagSeguroObj.brand != "undefined"){
183
+ $('card-brand').innerHTML = '<img src="https://stc.pagseguro.uol.com.br/public/img/payment-methods-flags/' +flag + '/' + RMPagSeguroObj.brand.name + '.png" alt="' + RMPagSeguroObj.brand.name + '" title="' + RMPagSeguroObj.brand.name + '"/>';
184
+ }
185
+ return;
 
 
 
186
  }
187
+ RMPagSeguroObj.cardBin = ccNum.substring(0, 6);
188
+ PagSeguroDirectPayment.getBrand({
189
+ cardBin: currentBin,
190
+ success: function(psresponse){
191
+ RMPagSeguroObj.brand = psresponse.brand;
192
+ $('card-brand').innerHTML = psresponse.brand.name;
193
+ if(RMPagSeguroObj.config.flag != ''){
194
 
195
+ $('card-brand').innerHTML = '<img src="https://stc.pagseguro.uol.com.br/public/img/payment-methods-flags/' +flag + '/' + psresponse.brand.name + '.png" alt="' + psresponse.brand.name + '" title="' + psresponse.brand.name + '"/>';
196
+ }
197
+ $('card-brand').className = psresponse.brand.name.replace(/[^a-zA-Z]*!/g,'');
198
+ },
199
+ error: function(psresponse){
200
+ console.error('Falha ao obter bandeira do cartão.');
201
+ if(RMPagSeguroObj.config.debug){
202
+ console.debug('Verifique a chamada para /getBin em df.uol.com.br no seu inspetor de Network a fim de obter mais detalhes.');
203
+ }
204
+ }
205
+ })
206
  }
207
+ },
208
+ updatePaymentHashes: function(){
209
+ var _url = RMPagSeguroSiteBaseURL + 'pseguro/ajax/updatePaymentHashes';
210
+ var _paymentHashes = {
211
+ "payment[sender_hash]": this.senderHash,
212
+ "payment[credit_card_token]": this.creditCardToken,
213
+ "payment[cc_type]": (this.brand)?this.brand.name:'',
214
+ "payment[is_admin]": this.config.is_admin
215
+ };
216
+ new Ajax.Request(_url, {
217
+ method: 'post',
218
+ parameters: _paymentHashes,
219
+ onSuccess: function(response){
220
+ if(RMPagSeguroObj.config.debug){
221
+ console.debug('Hashes atualizados com sucesso.');
222
+ console.debug(_paymentHashes);
223
  }
 
 
 
224
  },
225
+ onFailure: function(response){
226
+ if(RMPagSeguroObj.config.debug){
227
+ console.error('Falha ao atualizar os hashes da sessão.');
228
+ console.error(response);
229
+ }
230
+ return false;
231
  }
232
  });
233
+ },
234
+ getGrandTotal: function(){
235
+ if(this.config.is_admin){
236
+ return this.grandTotal;
 
 
 
 
 
 
 
 
237
  }
238
+ var _url = RMPagSeguroSiteBaseURL + 'pseguro/ajax/getGrandTotal';
 
 
 
239
  new Ajax.Request(_url, {
240
+ onSuccess: function(response){
241
+ RMPagSeguroObj.grandTotal = response.responseJSON.total;
242
+ RMPagSeguroObj.getInstallments(RMPagSeguroObj.grandTotal);
243
+ },
244
+ onFailure: function(response){
245
+ return false;
246
  }
247
  });
248
+ },
249
+ removeUnavailableBanks: function() {
250
+ if (RMPagSeguroObj.config.active_methods.tef) {
251
+ if($('pseguro_tef_bank').nodeName != "SELECT"){
252
+ //se houve customizações no elemento dropdown de bancos, não selecionaremos aqui
253
+ return;
254
+ }
255
  PagSeguroDirectPayment.getPaymentMethods({
256
+ amount: RMPagSeguroObj.grandTotal,
257
+ success: function (response) {
258
+ if (response.error == true && RMPagSeguroObj.config.debug) {
259
  console.log('Não foi possível obter os meios de pagamento que estão funcionando no momento.');
260
  return;
261
  }
262
+ if (RMPagSeguroObj.config.debug) {
263
+ console.log(response.paymentMethods);
264
+ }
265
+
266
+ try {
267
+ $('pseguro_tef_bank').options.length = 0;
268
+ for (y in response.paymentMethods.ONLINE_DEBIT.options) {
269
+ if (response.paymentMethods.ONLINE_DEBIT.options[y].status != 'UNAVAILABLE') {
270
+ var optName = response.paymentMethods.ONLINE_DEBIT.options[y].displayName.toString();
271
+ var optValue = response.paymentMethods.ONLINE_DEBIT.options[y].name.toString();
272
 
273
+ var optElm = new Element('option', {value: optValue}).update(optName);
274
+ $('pseguro_tef_bank').insert(optElm);
 
 
 
 
275
  }
276
  }
277
+
278
+ if(RMPagSeguroObj.config.debug){
279
+ console.info('Bancos TEF atualizados com sucesso.');
280
+ }
281
+ } catch (err) {
282
  console.log(err.message);
283
  }
284
  }
285
  })
286
  }
287
+ },
288
+ updateSessionId: function() {
289
+ var _url = RMPagSeguroSiteBaseURL + 'pseguro/ajax/getSessionId';
290
+ new Ajax.Request(_url, {
291
+ onSuccess: function (response) {
292
+ var session_id = response.responseJSON.session_id;
293
+ if(!session_id){
294
+ console.log('Não foi possível obter a session id do PagSeguro. Verifique suas configurações.');
295
+ }
296
+ PagSeguroDirectPayment.setSessionId(session_id);
297
  }
298
+ });
299
  }
 
 
300
  });
 
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>RicardoMartins_PagSeguro</name>
4
- <version>2.5.6</version>
5
  <stability>stable</stability>
6
  <license>MIT</license>
7
  <channel>community</channel>
@@ -13,9 +13,9 @@ Os dados do cart&#xE3;o s&#xE3;o enviados para o site do pagseguro de forma segu
13
  &#xD;
14
  Os bugs devem ser reportados na &#xE1;rea de Issues no github do projeto em https://github.com/r-martins/PagSeguro-Magento-Transparente</notes>
15
  <authors><author><name>Ricardo Martins</name><user>MAG001517858</user><email>ricardo@ricardomartins.info</email></author></authors>
16
- <date>2016-09-29</date>
17
- <time>14:25:27</time>
18
- <contents><target name="magecommunity"><dir name="RicardoMartins"><dir name="PagSeguro"><dir name="Block"><dir name="Form"><dir name="Cc"><file name="Dob.php" hash="ed45c9f5576c289897eb5c86a46c6d85"/></dir><file name="Cc.php" hash="23c8de35776d54f9717327ba8520f1b6"/><file name="Directpayment.php" hash="98ba4fb562b4ad777dc20b15ca345381"/><dir name="Info"><file name="Cc.php" hash="ef4952bfb9d12dae0b6ce13afeb0d1bb"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="f714d82e737808c49bbf623ff38c1823"/><file name="Internal.php" hash="5911252bc71b056c888a61df5f3bf58d"/><file name="Params.php" hash="8d614be2eafb974634a7108cf5311231"/></dir><dir name="Model"><file name="Abstract.php" hash="d0864beabaad0b8da84a4c0aadfbe85e"/><file name="Observer.php" hash="29a784cdb6203baf6b5f0abeeeda99ed"/><dir name="Payment"><file name="Cc.php" hash="b6201a7857ff683e660ae3ff566b1905"/></dir><dir name="Source"><dir name="Customer"><dir name="Address"><dir name="Attributes"><file name="Optional.php" hash="cb7cc6beb016941997051a9d5eb1014c"/></dir><file name="Attributes.php" hash="0ffab3cf1d51871f7d57d95dd95822ec"/></dir><file name="Attributes.php" hash="96c7da94017a8b38bd3804e9b0401a58"/><file name="Cpf.php" hash="da6e6525163d2ba954d69c687d101d7d"/><file name="Dob.php" hash="f82a41da22e5a84e77c35ff91d7dfab9"/></dir><file name="Paymentmethods.php" hash="88897d21a7b5217f834eda0daead22c3"/></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Token.php" hash="9d099f156f5bd6b18c8f315954da7b7f"/></dir><dir name="Source"><dir name="Customer"><file name="Groups.php" hash="f08bac32afcde8078a098446db79bc65"/></dir></dir></dir></dir></dir><dir name="Test"><dir name="Helper"><file name="Params.php" hash="a596ea4060cdfe0a4d7e981d9543301f"/></dir></dir><dir name="controllers"><file name="AjaxController.php" hash="89b915bbfc061beb7550a56248177c9f"/><file name="NotificationController.php" hash="e7056961e4ada5cc5614c5a40ef78a75"/><file name="TestController.php" hash="0e2c2bd2fc77ced55f880d1860e4318d"/></dir><dir name="etc"><file name="config.xml" hash="3bb557733051e0af3d097937b4291674"/><file name="system.xml" hash="cdb81843dc7f5023a2d35ca1fd0dcdd8"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="RicardoMartins_PagSeguro.xml" hash="82d8294eccac1fb4047f27566b0c9f2a"/></dir></target><target name="magelocale"><dir name="pt_BR"><file name="RicardoMartins_PagSeguro.csv" hash="84a6cc4fb73769ac822c9e8e22b8cec8"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="pagseguro"><dir><dir name="selo"><file name="selo01_160x90.gif" hash="e6729bb969abb20588f134f7d29ea0ec"/><file name="selo01_200x60.gif" hash="e91ed131018bae7d9abc2cc1a72f539b"/><file name="selo01_300x60.gif" hash="13b07e35250b30a61c86c98815e3310c"/><file name="selo02_160x90.gif" hash="4e65530d2c42bae4e5fab617a4d0afdf"/><file name="selo02_200x60.gif" hash="ba629a85cef8982423c7679a4875283c"/><file name="selo02_300x60.gif" hash="5827aca40455f22caffee1392917f16c"/><file name="selo03_160x90.gif" hash="e3c69ace0991d7841728c6203fc305bf"/><file name="selo03_200x60.gif" hash="63135b65df64a70629748d66f5c0c453"/><file name="selo03_300x60.gif" hash="e88f1529f2d27d4732cd7c374752618e"/><file name="selo04_160x90.gif" hash="8e71cb1942c15427ba96ac21aacdb9d6"/><file name="selo04_200x60.gif" hash="f08b80b40541e35491a8d966cb420c78"/><file name="selo04_300x60.gif" hash="43f9fc4ad730111654777c26059e9fbf"/></dir></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="ricardomartins_pagseguro"><dir><dir name="form"><dir name="cc"><file name="dob.phtml" hash="0ea9d4ff767a43d1393ddf1e2882a5da"/></dir><file name="cc.phtml" hash="1e5f98f09a867256ddfbd17b22320dcb"/><file name="directpayment.phtml" hash="ff5cb599a494f436024fd63a96f0420c"/><dir name="info"><file name="cc.phtml" hash="0a3aa78e0775cd51bb7a168b813dd466"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="template"><dir name="ricardomartins_pagseguro"><dir><dir name="form"><file name="directpayment.phtml" hash="70b426d9f7a245a758a085ba2d188f92"/><dir name="info"><file name="cc.phtml" hash="0a3aa78e0775cd51bb7a168b813dd466"/></dir></dir></dir></dir></dir><dir name="layout"><dir name="ricardomartins_pagseguro"><file name="pagseguro.xml" hash="dabe29bc130ac063b1715a66f979b131"/></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="pagseguro"><file name="pagseguro.js" hash="9d1f6296b6ad68555ac9a61cdc5f9365"/></dir></dir></target></contents>
19
  <compatible/>
20
- <dependencies><required><php><min>5.2.1</min><max>5.7.5</max></php></required></dependencies>
21
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>RicardoMartins_PagSeguro</name>
4
+ <version>3.0.1</version>
5
  <stability>stable</stability>
6
  <license>MIT</license>
7
  <channel>community</channel>
13
  &#xD;
14
  Os bugs devem ser reportados na &#xE1;rea de Issues no github do projeto em https://github.com/r-martins/PagSeguro-Magento-Transparente</notes>
15
  <authors><author><name>Ricardo Martins</name><user>MAG001517858</user><email>ricardo@ricardomartins.info</email></author></authors>
16
+ <date>2017-01-22</date>
17
+ <time>20:05:14</time>
18
+ <contents><target name="magecommunity"><dir name="RicardoMartins"><dir name="PagSeguro"><dir name="Block"><dir name="Form"><dir name="Cc"><file name="Dob.php" hash="ed45c9f5576c289897eb5c86a46c6d85"/></dir><file name="Cc.php" hash="23c8de35776d54f9717327ba8520f1b6"/><file name="Directpayment.php" hash="98ba4fb562b4ad777dc20b15ca345381"/><dir name="Info"><file name="Cc.php" hash="ef4952bfb9d12dae0b6ce13afeb0d1bb"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="4543a0aa35dd7aa4b9b6686a54dd5dd4"/><file name="Internal.php" hash="faed0e7778904c2b74a0632c1ae2f844"/><file name="Params.php" hash="3ae7733c2dd439513a933c69093440d8"/></dir><dir name="Model"><file name="Abstract.php" hash="d4965dae31f3966a4cfd0c1476f70b41"/><file name="Observer.php" hash="6a9d4a53e3cc3c527940d7603b0b1e40"/><dir name="Payment"><file name="Cc.php" hash="b4e1712e860f56305c18b9312454fc6c"/></dir><dir name="Source"><file name="Ccbrand.php" hash="d9696c3a2854d5e07fb96af55929e738"/><dir name="Customer"><dir name="Address"><dir name="Attributes"><file name="Optional.php" hash="cb7cc6beb016941997051a9d5eb1014c"/></dir><file name="Attributes.php" hash="0ffab3cf1d51871f7d57d95dd95822ec"/></dir><file name="Attributes.php" hash="96c7da94017a8b38bd3804e9b0401a58"/><file name="Cpf.php" hash="da6e6525163d2ba954d69c687d101d7d"/><file name="Dob.php" hash="f82a41da22e5a84e77c35ff91d7dfab9"/></dir><file name="Paymentmethods.php" hash="88897d21a7b5217f834eda0daead22c3"/></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Token.php" hash="9d099f156f5bd6b18c8f315954da7b7f"/></dir><dir name="Source"><dir name="Customer"><file name="Groups.php" hash="f08bac32afcde8078a098446db79bc65"/></dir></dir></dir></dir></dir><dir name="Test"><dir name="Helper"><file name="Params.php" hash="a596ea4060cdfe0a4d7e981d9543301f"/></dir></dir><dir name="controllers"><file name="AjaxController.php" hash="c7db6498379d63ef44a3848af6daf987"/><file name="NotificationController.php" hash="e7056961e4ada5cc5614c5a40ef78a75"/><file name="TestController.php" hash="19594af040ac8e903d91e90d608188be"/></dir><dir name="data"><dir name="ricardomartins_pagseguro_setup"><file name="data-install-3.0.0.php" hash="038f4e1d3ff6e8b18b46c356f8499025"/></dir></dir><dir name="etc"><file name="config.xml" hash="c831a40f55750057e4c72159c09d5330"/><file name="system.xml" hash="124a9a8a6a50b43ee9d8320e86eaa53f"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="RicardoMartins_PagSeguro.xml" hash="82d8294eccac1fb4047f27566b0c9f2a"/></dir></target><target name="magelocale"><dir name="pt_BR"><file name="RicardoMartins_PagSeguro.csv" hash="84a6cc4fb73769ac822c9e8e22b8cec8"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="pagseguro"><dir><dir name="selo"><file name="brflag.png" hash="ed8f0f1d2cd9cd7bc9a8584af417601e"/><file name="selo01_160x90.gif" hash="e6729bb969abb20588f134f7d29ea0ec"/><file name="selo01_200x60.gif" hash="e91ed131018bae7d9abc2cc1a72f539b"/><file name="selo01_300x60.gif" hash="13b07e35250b30a61c86c98815e3310c"/><file name="selo02_160x90.gif" hash="4e65530d2c42bae4e5fab617a4d0afdf"/><file name="selo02_200x60.gif" hash="ba629a85cef8982423c7679a4875283c"/><file name="selo02_300x60.gif" hash="5827aca40455f22caffee1392917f16c"/><file name="selo03_160x90.gif" hash="e3c69ace0991d7841728c6203fc305bf"/><file name="selo03_200x60.gif" hash="63135b65df64a70629748d66f5c0c453"/><file name="selo03_300x60.gif" hash="e88f1529f2d27d4732cd7c374752618e"/><file name="selo04_160x90.gif" hash="8e71cb1942c15427ba96ac21aacdb9d6"/><file name="selo04_200x60.gif" hash="f08b80b40541e35491a8d966cb420c78"/><file name="selo04_300x60.gif" hash="43f9fc4ad730111654777c26059e9fbf"/></dir></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="ricardomartins_pagseguro"><dir><dir name="form"><dir name="cc"><file name="dob.phtml" hash="0545c2e8967213c298802723d9b1a1a2"/></dir><file name="cc.phtml" hash="da91dec818b2d7485ecbebcedfe5a087"/><file name="directpayment.phtml" hash="754716867f9bb46edd6942a45997f666"/><dir name="info"><file name="cc.phtml" hash="0a3aa78e0775cd51bb7a168b813dd466"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="template"><dir name="ricardomartins_pagseguro"><dir><dir name="form"><dir name="cc"><file name="dob.phtml" hash="0545c2e8967213c298802723d9b1a1a2"/></dir><file name="cc.phtml" hash="90da6037169e70719e98f28f2a44abd9"/><file name="directpayment.phtml" hash="2b6de8deb0560a2d0a9898e887bf1a84"/><dir name="info"><file name="cc.phtml" hash="0a3aa78e0775cd51bb7a168b813dd466"/></dir></dir></dir></dir></dir><dir name="layout"><dir name="ricardomartins_pagseguro"><file name="pagseguro.xml" hash="dabe29bc130ac063b1715a66f979b131"/></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="pagseguro"><file name="card.js" hash="2446373da8bcf1712515d85ad481a464"/><file name="pagseguro.js" hash="44eb951a26fc01fce4d8e21da3595c95"/></dir></dir></target></contents>
19
  <compatible/>
20
+ <dependencies><required><php><min>5.2.1</min><max>7.5.0</max></php></required></dependencies>
21
  </package>
skin/frontend/base/default/pagseguro/selo/brflag.png ADDED
Binary file