uc_credit.test 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. /**
  3. * @file
  4. * Credit card payment method tests.
  5. */
  6. /**
  7. * Tests credit card payments with the test gateway.
  8. *
  9. * This class is intended to be subclassed for use in testing other credit
  10. * card gateways. Subclasses which test other gateways need to:
  11. * - Define getInfo().
  12. * - Override setUp(), if necessary, to enable the other gateway and any other
  13. * needed modules.
  14. * - Override configureGateway() to implement gateway-specific configuration.
  15. * No other overrides are necessary, although a subclass may want to add
  16. * additional test functions to cover cases not included in this base class.
  17. */
  18. class UbercartCreditCardTestCase extends UbercartTestHelper {
  19. /**
  20. * A selection of "test" numbers to use for testing credit card payemnts.
  21. * These numbers all pass the Luhn algorithm check and are reserved by
  22. * the card issuer for testing purposes.
  23. */
  24. protected static $test_cards = array(
  25. '378282246310005', // American Express
  26. '371449635398431',
  27. '370000000000002',
  28. '378734493671000', // American Express Corporate
  29. '5610591081018250', // Australian BankCard
  30. '30569309025904', // Diners Club
  31. '38520000023237',
  32. '38000000000006', // Carte Blanche
  33. '6011111111111117', // Discover
  34. '6011000990139424',
  35. '6011000000000012',
  36. '3530111333300000', // JCB
  37. '3566002020360505',
  38. '3088000000000017',
  39. '5555555555554444', // MasterCard
  40. '5105105105105100',
  41. '4111111111111111', // Visa
  42. '4012888888881881',
  43. '4007000000027',
  44. '4012888818888',
  45. );
  46. /**
  47. * Describes this test case.
  48. */
  49. public static function getInfo() {
  50. return array(
  51. 'name' => 'Credit cards with Test Gateway',
  52. 'description' => 'Uses the Test Gateway to ensure credit card processing is functioning.',
  53. 'group' => 'Ubercart',
  54. );
  55. }
  56. /**
  57. * Implements DrupalWebTestCase::setUp().
  58. */
  59. protected function setUp($modules = array(), $permissions = array()) {
  60. $modules += array('uc_payment', 'uc_credit', 'test_gateway');
  61. $permissions = array('administer credit cards', 'process credit cards');
  62. parent::setUp($modules, $permissions);
  63. // Need admin permissions in order to change credit card settings.
  64. $this->drupalLogin($this->adminUser);
  65. // Configure and enable Credit card module and Test gateway.
  66. $this->configureCreditCard();
  67. $this->configureGateway();
  68. }
  69. /**
  70. * Helper function to configure Credit Card payment method settings.
  71. */
  72. protected function configureCreditCard() {
  73. $this->drupalPost(
  74. 'admin/store/settings/payment',
  75. array('uc_payment_method_credit_checkout' => TRUE),
  76. t('Save configuration')
  77. );
  78. $this->assertFieldByName(
  79. 'uc_payment_method_credit_checkout',
  80. TRUE,
  81. t('Credit card payment method is enabled')
  82. );
  83. // Create key directory, make it readable and writeable.
  84. // Putting this under sites/default/files because SimpleTest needs to be
  85. // able to create the directory - this is NOT where you'd put the key file
  86. // on a live site. On a live site, it should be outside the web root.
  87. drupal_mkdir('sites/default/files/simpletest.keys', 0755);
  88. $this->drupalPost(
  89. 'admin/store/settings/payment/method/credit',
  90. array(
  91. 'uc_credit_encryption_path' => 'sites/default/files/simpletest.keys',
  92. ),
  93. t('Save configuration')
  94. );
  95. $this->assertFieldByName(
  96. 'uc_credit_encryption_path',
  97. 'sites/default/files/simpletest.keys',
  98. t('Key file path has been set.')
  99. );
  100. $this->assertTrue(
  101. file_exists('sites/default/files/simpletest.keys/' . UC_CREDIT_KEYFILE_NAME),
  102. t('Key has been generated and stored.')
  103. );
  104. $this->pass('Key = ' . uc_credit_encryption_key());
  105. }
  106. /**
  107. * Helper function to configure Credit Card gateway.
  108. */
  109. protected function configureGateway() {
  110. $this->drupalPost(
  111. 'admin/store/settings/payment/method/credit',
  112. array(
  113. 'uc_payment_credit_gateway' => 'test_gateway',
  114. 'uc_pg_test_gateway_enabled' => TRUE,
  115. ),
  116. t('Save configuration')
  117. );
  118. $this->assertFieldByName(
  119. 'uc_pg_test_gateway_enabled',
  120. TRUE,
  121. t('Test gateway is enabled')
  122. );
  123. }
  124. /**
  125. * Implements DrupalWebTestCase::tearDown().
  126. */
  127. protected function tearDown() {
  128. // Cleanup keys directory after test.
  129. drupal_unlink('sites/default/files/simpletest.keys/' . UC_CREDIT_KEYFILE_NAME);
  130. drupal_rmdir('sites/default/files/simpletest.keys');
  131. parent::tearDown();
  132. }
  133. /**
  134. * Helper function. Creates a new order.
  135. */
  136. protected function createOrder($fields = array()) {
  137. $order = uc_order_new();
  138. foreach ($fields as $key => $value) {
  139. $order->$key = $value;
  140. }
  141. if (empty($order->primary_email)) {
  142. $order->primary_email = $this->randomString() . '@example.org';
  143. }
  144. if (!isset($fields['products'])) {
  145. $item = clone $this->product;
  146. $item->qty = 1;
  147. $item->price = $item->sell_price;
  148. $item->data = array();
  149. $order->products = array($item);
  150. }
  151. $order->order_total = uc_order_get_total($order, TRUE);
  152. $order->line_items = uc_order_load_line_items($order, TRUE);
  153. uc_order_save($order);
  154. return $order;
  155. }
  156. /**
  157. * Tests security settings configuration.
  158. */
  159. public function testSecuritySettings() {
  160. // TODO: Still need tests with existing key file
  161. // where key file is not readable or doesn't contain a valid key
  162. // Create key directory, make it readable and writeable.
  163. drupal_mkdir('sites/default/files/testkey', 0755);
  164. // Try to submit settings form without a key file path.
  165. // Save current variable, reset to its value when first installed.
  166. $temp_variable = variable_get('uc_credit_encryption_path', '');
  167. variable_set('uc_credit_encryption_path', '');
  168. $this->drupalGet('admin/store/settings/payment/method/credit');
  169. $this->assertText(t('Credit card security settings must be configured in the security settings tab.'));
  170. $this->drupalPost(
  171. 'admin/store/settings/payment/method/credit',
  172. array(),
  173. t('Save configuration')
  174. );
  175. $this->assertFieldByName(
  176. 'uc_credit_encryption_path',
  177. t('Not configured.'),
  178. t('Key file has not yet been configured.')
  179. );
  180. // Restore variable setting.
  181. variable_set('uc_credit_encryption_path', $temp_variable);
  182. // Try to submit settings form with an empty key file path.
  183. $this->drupalPost(
  184. 'admin/store/settings/payment/method/credit',
  185. array('uc_credit_encryption_path' => ''),
  186. t('Save configuration')
  187. );
  188. $this->assertText('Key path must be specified in security settings tab.');
  189. // Specify non-existent directory
  190. $this->drupalPost(
  191. 'admin/store/settings/payment/method/credit',
  192. array('uc_credit_encryption_path' => 'sites/default/ljkh/asdfasfaaaaa'),
  193. t('Save configuration')
  194. );
  195. $this->assertText('You have specified a non-existent directory.');
  196. // Next, specify existing directory that's write protected.
  197. // Use /dev, as that should never be accessible.
  198. $this->drupalPost(
  199. 'admin/store/settings/payment/method/credit',
  200. array('uc_credit_encryption_path' => '/dev'),
  201. t('Save configuration')
  202. );
  203. $this->assertText('Cannot write to directory, please verify the directory permissions.');
  204. // Next, specify writeable directory, but with excess whitespace
  205. // and trailing /
  206. $this->drupalPost(
  207. 'admin/store/settings/payment/method/credit',
  208. array('uc_credit_encryption_path' => ' sites/default/files/testkey/ '),
  209. t('Save configuration')
  210. );
  211. // See that the directory has been properly re-written to remove
  212. // whitespace and trailing /
  213. $this->assertFieldByName(
  214. 'uc_credit_encryption_path',
  215. 'sites/default/files/testkey',
  216. t('Key file path has been set.')
  217. );
  218. $this->assertText('Credit card encryption key file generated.');
  219. // Check that warning about needing key file goes away.
  220. $this->assertNoText(t('Credit card security settings must be configured in the security settings tab.'));
  221. // Remove key file.
  222. drupal_unlink('sites/default/files/testkey/' . UC_CREDIT_KEYFILE_NAME);
  223. // Finally, specify good directory
  224. $this->drupalPost(
  225. 'admin/store/settings/payment/method/credit',
  226. array('uc_credit_encryption_path' => 'sites/default/files/testkey'),
  227. t('Save configuration')
  228. );
  229. $this->assertText('Credit card encryption key file generated.');
  230. // Test contents - must contain 32-character hexadecimal string.
  231. $this->assertTrue(
  232. file_exists('sites/default/files/simpletest.keys/' . UC_CREDIT_KEYFILE_NAME),
  233. t('Key has been generated and stored.')
  234. );
  235. $this->assertTrue(
  236. preg_match("([0-9a-fA-F]{32})", uc_credit_encryption_key()),
  237. t('Valid key detected in key file.')
  238. );
  239. // Cleanup keys directory after test.
  240. drupal_unlink('sites/default/files/testkey/' . UC_CREDIT_KEYFILE_NAME);
  241. drupal_rmdir('sites/default/files/testkey');
  242. }
  243. /**
  244. * Tests that an order can be placed using the test gateway.
  245. */
  246. public function testCheckout() {
  247. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  248. $this->checkout(array(
  249. 'panes[payment][details][cc_number]' => array_rand(array_flip(self::$test_cards)),
  250. 'panes[payment][details][cc_cvv]' => mt_rand(100, 999),
  251. 'panes[payment][details][cc_exp_month]' => mt_rand(1, 12),
  252. 'panes[payment][details][cc_exp_year]' => mt_rand(date('Y') + 1, 2022),
  253. ));
  254. $this->assertText('Your order is complete!');
  255. }
  256. /**
  257. * Tests that expiry date validation functions correctly.
  258. */
  259. public function testExpiryDate() {
  260. $order = $this->createOrder(array('payment_method' => 'credit'));
  261. $year = date('Y');
  262. $month = date('n');
  263. for ($y = $year; $y <= $year + 2; $y++) {
  264. for ($m = 1; $m <= 12; $m++) {
  265. $edit = array(
  266. 'amount' => 1,
  267. 'cc_data[cc_number]' => '4111111111111111',
  268. 'cc_data[cc_cvv]' => '123',
  269. 'cc_data[cc_exp_month]' => $m,
  270. 'cc_data[cc_exp_year]' => $y,
  271. );
  272. $this->drupalPost('admin/store/orders/' . $order->order_id . '/credit', $edit, 'Charge amount');
  273. if ($y > $year || $m >= $month) {
  274. $this->assertText('The credit card was processed successfully.', t('Card with expiry date @month/@year passed validation.', array('@month' => $m, '@year' => $y)));
  275. }
  276. else {
  277. $this->assertNoText('The credit card was processed successfully.', t('Card with expiry date @month/@year correctly failed validation.', array('@month' => $m, '@year' => $y)));
  278. }
  279. }
  280. }
  281. }
  282. }