WC_GZD_Gateway_Direct_Debit

Direct Debit Payment Gateway.

Defined (1)

The class is defined in the following location(s).

/includes/gateways/direct-debit/class-wc-gzd-gateway-direct-debit.php  
  1. class WC_GZD_Gateway_Direct_Debit extends WC_Payment_Gateway { 
  2.  
  3. /** 
  4. * Constructor for the gateway. 
  5. */ 
  6. public function __construct() { 
  7. $this->id = 'direct-debit'; 
  8. $this->icon = apply_filters( 'woocommerce_gzd_direct_debit_icon', '' ); 
  9. $this->has_fields = true; 
  10. $this->method_title = __( 'Direct Debit', 'woocommerce-germanized' ); 
  11. $this->method_description = sprintf( __( 'Allows you to offer direct debit as a payment method to your customers. Adds SEPA fields to checkout. %s', 'woocommerce-germanized' ), '<a class="button button-secondary" href="' . admin_url( 'export.php' ) . '">' . __( 'SEPA XML Bulk Export', 'woocommerce-germanized' ) . '</a>' ); 
  12.  
  13. // Load the settings. 
  14. $this->init_form_fields(); 
  15. $this->init_settings(); 
  16.  
  17. // Define user set variables 
  18. $this->enabled = $this->get_option( 'enabled' ); 
  19. $this->title = $this->get_option( 'title' ); 
  20. $this->description = $this->get_option( 'description' ); 
  21. $this->instructions = $this->get_option( 'instructions', $this->description ); 
  22. $this->enable_checkbox = $this->get_option( 'enable_checkbox', 'yes' ); 
  23. $this->generate_mandate_id = $this->get_option( 'generate_mandate_id', 'yes' ); 
  24. $this->mandate_id_format = $this->get_option( 'mandate_id_format', 'MANDAT{id}' ); 
  25. $this->company_info = $this->get_option( 'company_info' ); 
  26. $this->company_identification_number = $this->get_option( 'company_identification_number' ); 
  27. $this->company_account_holder = $this->get_option( 'company_account_holder' ); 
  28. $this->company_account_iban = $this->get_option( 'company_account_iban' ); 
  29. $this->company_account_bic = $this->get_option( 'company_account_bic' ); 
  30. $this->checkbox_label = $this->get_option( 'checkbox_label' ); 
  31. $this->remember = $this->get_option( 'remember', 'no' ); 
  32. $this->mask = $this->get_option( 'mask', 'yes' ); 
  33. $this->mandate_text = $this->get_option( 'mandate_text', __( '[company_info] 
  34. debtee identification number: [company_identification_number] 
  35. mandat reference number: [mandate_id]. 
  36.  
  37. <h3>SEPA Direct Debit Mandate</h3> 
  38.  
  39. I hereby authorize the payee to automatically draft from my savings account listed below for the specified amount. I further authorize my bank to accept the direct debit from this account. 
  40.  
  41. Notice: I may request a full refund within eight weeks starting with the initial debiting date. Responsibilities agreed with my credit institute apply for a refund. 
  42.  
  43. <strong>Debtor:</strong> 
  44. Account holder: [account_holder] 
  45. Street: [street] 
  46. Postcode: [postcode] 
  47. City: [city] 
  48. Country: [country] 
  49. IBAN: [account_iban] 
  50. BIC: [account_swift] 
  51.  
  52. [city], [date], [account_holder] 
  53.  
  54. This letter is done automatically and is valid without signature. 
  55.  
  56. <hr/> 
  57.  
  58. Please notice: Period for pre-information of the SEPA direct debit is shortened to one day.', 'woocommerce-germanized' ) ); 
  59.  
  60. $this->supports = array( 
  61. 'products',  
  62. 'subscriptions' 
  63. ); 
  64.  
  65. if ( $this->get_option( 'enabled' ) === 'yes' && ! $this->supports_encryption() ) { 
  66.  
  67. ob_start(); 
  68. include_once( 'views/html-encryption-notice.php' ); 
  69. $notice = ob_get_clean(); 
  70.  
  71. $this->method_description .= $notice; 
  72.  
  73.  
  74. // Force disabling remember account data if encryption is not supported 
  75. if ( ! $this->supports_encryption() ) { 
  76. $this->remember = 'no'; 
  77.  
  78. // Actions 
  79. add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); 
  80. add_action( 'woocommerce_thankyou_direct-debit', array( $this, 'thankyou_page' ) ); 
  81. add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) ); 
  82. add_action( 'woocommerce_review_order_after_payment', array( $this, 'checkbox' ), wc_gzd_get_hook_priority( 'checkout_direct_debit' ) ); 
  83. add_action( 'wp_ajax_show_direct_debit', array( $this, 'generate_mandate' ) ); 
  84. add_action( 'wp_ajax_nopriv_show_direct_debit', array( $this, 'generate_mandate' ) ); 
  85. add_filter( 'woocommerce_email_classes', array( $this, 'add_email_template' ) ); 
  86.  
  87. add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_checkbox' ) ); 
  88.  
  89. // Pay for Order 
  90. add_action( 'woocommerce_pay_order_before_submit', array( $this, 'checkbox' ) ); 
  91.  
  92. // Order Meta 
  93. add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'set_order_meta' ), 10, 2 ); 
  94.  
  95. // Customer Emails 
  96. add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 ); 
  97. add_action( 'woocommerce_germanized_order_confirmation_sent', array( $this, 'send_mail' ) ); 
  98. add_action( 'woocommerce_email_customer_details', array( $this, 'email_sepa' ), 15, 3 ); 
  99.  
  100. // Order admin 
  101. add_filter( 'woocommerce_admin_billing_fields', array( $this, 'set_debit_fields' ) ); 
  102. // Admin order table download actions 
  103. add_filter( 'woocommerce_admin_order_actions', array( $this, 'order_actions' ), 0, 2 ); 
  104.  
  105. // Export filters 
  106. add_action( 'export_filters', array( $this, 'export_view' ) ); 
  107. add_action( 'export_wp', array( $this, 'export' ), 0, 1 ); 
  108. add_filter( 'export_args', array( $this, 'export_args' ), 0, 1 ); 
  109.  
  110.  
  111. public function order_actions( $actions, $order ) { 
  112.  
  113. if ( $order->payment_method === $this->id ) { 
  114. $actions[ 'download-sepa' ] = array( 
  115. 'url' => add_query_arg( array( 'download' => 'true', 'content' => 'sepa', 'sepa_order_id' => $order->id ), admin_url( 'export.php' ) ),  
  116. 'name' => __( 'SEPA XML Export', 'woocommerce-germanized' ),  
  117. 'action' => "xml" 
  118. ); 
  119.  
  120. return $actions; 
  121.  
  122. public function export_view() { 
  123. include_once( 'views/html-export.php' ); 
  124.  
  125. public function export_args( $args = array() ) { 
  126. if ( 'sepa' === $_GET['content'] ) { 
  127. $args['content'] = 'sepa'; 
  128. if ( isset( $_GET['sepa_start_date'] ) || isset( $_GET['sepa_end_date'] ) ) { 
  129. $args['start_date'] = ( isset( $_GET['sepa_start_date'] ) ? sanitize_text_field( $_GET['sepa_start_date'] ) : '' ); 
  130. $args['end_date'] = ( isset( $_GET['sepa_end_date'] ) ? sanitize_text_field( $_GET['sepa_end_date'] ) : '' ); 
  131. } else if ( isset( $_GET[ 'sepa_order_id' ] ) ) { 
  132. $args['order_id'] = absint( $_GET['sepa_order_id'] ); 
  133. return $args; 
  134.  
  135. public function export( $args = array() ) { 
  136.  
  137. if ( $args[ 'content' ] != 'sepa' ) 
  138. return; 
  139.  
  140. $filename = ''; 
  141. $parts = array( 'SEPA-Export' ); 
  142.  
  143. $query_args = array( 
  144. 'post_type' => 'shop_order',  
  145. 'post_status' => array_keys( wc_get_order_statuses() ),  
  146. 'orderby' => 'post_date',  
  147. 'order' => 'ASC',  
  148. 'meta_query' => array( 
  149. array( 
  150. 'key' => '_payment_method',  
  151. 'value' => 'direct-debit',  
  152. 'compare' => '=',  
  153. ),  
  154. ),  
  155. ); 
  156.  
  157. if ( isset( $args['order_id'] ) ) { 
  158.  
  159. $query_args[ 'p' ] = absint( $args['order_id'] ); 
  160. array_push( $parts, 'order-' . absint( $args['order_id'] ) ); 
  161.  
  162. } else { 
  163.  
  164. $query_args = array_merge( $query_args, array( 
  165. 'showposts' => -1,  
  166. 'date_query' => array( 
  167. array( 
  168. 'after' => $args['start_date'],  
  169. 'before' => $args['end_date'],  
  170. 'inclusive' => true,  
  171. ),  
  172. ),  
  173. ) ); 
  174.  
  175. if ( ! empty( $args['start_date'] ) ) 
  176. array_push( $parts, $args['start_date'] ); 
  177. if ( ! empty( $args['end_date'] ) ) 
  178. array_push( $parts, $args['end_date'] ); 
  179.  
  180.  
  181. $order_query = new WP_Query( $query_args ); 
  182. $filename = apply_filters( 'woocommerce_germanized_direct_debit_export_filename', implode( '-', $parts ) . '.xml', $args ); 
  183.  
  184. if ( $order_query->have_posts() ) { 
  185.  
  186. include_once( 'libraries/sepa-xml-creator/SepaXmlCreator.php' ); 
  187. $creator = new SepaXmlCreator(); 
  188.  
  189. $creator->setAccountValues( $this->company_account_holder, $this->company_account_iban, $this->company_account_bic ); 
  190. $creator->setGlaeubigerId( $this->company_identification_number ); 
  191.  
  192. while ( $order_query->have_posts() ) { 
  193.  
  194. $order_query->next_post(); 
  195. $order = wc_get_order( $order_query->post->ID ); 
  196.  
  197. $book = new SepaBuchung(); 
  198. $book->setBetrag( $order->get_total() ); 
  199. $book->setBic( $this->maybe_decrypt( $order->direct_debit_bic ) ); 
  200. $book->setName( $order->direct_debit_holder ); 
  201. $book->setIban( $this->maybe_decrypt( $order->direct_debit_iban ) ); 
  202. $book->setName( $order->direct_debit_holder ); 
  203. $book->setVerwendungszweck( apply_filters( 'woocommerce_germanized_direct_debit_purpose', sprintf( __( 'Order %s', 'woocommerce-germanized' ), $order->get_order_number() ) ), $order ); 
  204. $book->setMandat( $this->get_mandate_id( $order->id ), date_i18n( "Y-m-d", strtotime( $order->order_date ) ), false ); 
  205. $creator->addBuchung( $book ); 
  206.  
  207.  
  208. $sepaxml = $creator->generateBasislastschriftXml(); 
  209.  
  210. header( 'Content-Description: File Transfer' ); 
  211. header( 'Content-Disposition: attachment; filename=' . $filename ); 
  212. header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true ); 
  213. header( 'Cache-Control: no-cache, no-store, must-revalidate' );  
  214. header( 'Pragma: no-cache' ); 
  215. header( 'Expires: 0' ); 
  216.  
  217. echo $sepaxml; 
  218. exit(); 
  219.  
  220. }  
  221.  
  222.  
  223. public function get_mandate_id( $order_id = false ) { 
  224.  
  225. if ( ! $order_id ) 
  226. return __( 'Will be notified separately', 'woocommerce-germanized' ); 
  227.  
  228. $order = wc_get_order( $order_id ); 
  229.  
  230. if ( $order->direct_debit_mandate_id ) 
  231. return $order->direct_debit_mandate_id; 
  232.  
  233. $mandate_id = apply_filters( 'woocommerce_germanized_direct_debit_mandate_id', ( $this->generate_mandate_id === 'yes' ? str_replace( '{id}', $order->get_order_number(), $this->mandate_id_format ) : '' ) ); 
  234. update_post_meta( $order->id, '_direct_debit_mandate_id', $mandate_id ); 
  235.  
  236. return $mandate_id; 
  237.  
  238. public function email_sepa( $order, $sent_to_admin, $plain_text ) { 
  239.  
  240. if ( $this->id !== $order->payment_method ) 
  241. return; 
  242.  
  243. $sepa_fields = array( 
  244. __( 'Account Holder', 'woocommerce-germanized' ) => $order->direct_debit_holder,  
  245. __( 'IBAN', 'woocommerce-germanized' ) => $this->mask( $this->maybe_decrypt( $order->direct_debit_iban ) ),  
  246. __( 'BIC/SWIFT', 'woocommerce-germanized' ) => $this->maybe_decrypt( $order->direct_debit_bic ),  
  247. ); 
  248.  
  249. wc_get_template( 'emails/email-sepa-data.php', array( 'fields' => $sepa_fields ) ); 
  250.  
  251.  
  252. public function set_debit_fields( $fields ) { 
  253.  
  254. global $post; 
  255.  
  256. $order = wc_get_order( $post->ID ); 
  257.  
  258. if ( ! $order->payment_method == $this->id ) 
  259. return $fields; 
  260.  
  261. $fields[ 'direct_debit_holder' ] = array( 
  262. 'label' => __( 'Account Holder', 'woocommerce-germanized' ),  
  263. 'id' => '_direct_debit_holder',  
  264. 'class' => '',  
  265. 'show' => true,  
  266. ); 
  267.  
  268. $fields[ 'direct_debit_iban' ] = array( 
  269. 'label' => __( 'IBAN', 'woocommerce-germanized' ),  
  270. 'id' => '_direct_debit_iban',  
  271. 'value' => $this->maybe_decrypt( get_post_meta( $order->id, '_direct_debit_iban', true ) ),  
  272. 'show' => true,  
  273. ); 
  274.  
  275. $fields[ 'direct_debit_bic' ] = array( 
  276. 'label' => __( 'BIC/SWIFT', 'woocommerce-germanized' ),  
  277. 'id' => '_direct_debit_bic',  
  278. 'value' => $this->maybe_decrypt( get_post_meta( $order->id, '_direct_debit_bic', true ) ),  
  279. 'show' => true,  
  280. ); 
  281.  
  282. $fields[ 'direct_debit_mandate_id' ] = array( 
  283. 'label' => __( 'Mandate Reference ID', 'woocommerce-germanized' ),  
  284. 'id' => '_direct_debit_mandate_id',  
  285. 'show' => true,  
  286. ); 
  287.  
  288. return $fields; 
  289.  
  290.  
  291. public function send_mail( $order_id ) { 
  292.  
  293. $order = wc_get_order( $order_id ); 
  294.  
  295. if ( $order->payment_method == $this->id ) { 
  296. if ( $mail = WC_germanized()->emails->get_email_instance_by_id( 'customer_sepa_direct_debit_mandate' ) ) 
  297. $mail->trigger( $order ); 
  298.  
  299.  
  300. public function set_order_meta( $order_id, $posted ) { 
  301.  
  302. $order = wc_get_order( $order_id ); 
  303.  
  304. if ( ! $order->payment_method == $this->id ) 
  305. return; 
  306.  
  307. $holder = ( isset( $_POST[ 'direct_debit_account_holder' ] ) ? wc_clean( $_POST[ 'direct_debit_account_holder' ] ) : '' ); 
  308. $iban = ( isset( $_POST[ 'direct_debit_account_iban' ] ) ? $this->maybe_encrypt( wc_clean( $_POST[ 'direct_debit_account_iban' ] ) ) : '' ); 
  309. $bic = ( isset( $_POST[ 'direct_debit_account_bic' ] ) ? $this->maybe_encrypt( wc_clean( $_POST[ 'direct_debit_account_bic' ] ) ) : '' ); 
  310.  
  311. update_post_meta( $order->id, '_direct_debit_holder', $holder ); 
  312. update_post_meta( $order->id, '_direct_debit_iban', $iban ); 
  313. update_post_meta( $order->id, '_direct_debit_bic', $bic ); 
  314.  
  315. if ( ! $this->supports_encryption() || $this->remember === 'no' || ! $order->customer_user ) 
  316. return; 
  317.  
  318. update_user_meta( $order->customer_user, 'direct_debit_holder', $holder ); 
  319. update_user_meta( $order->customer_user, 'direct_debit_iban', $iban ); 
  320. update_user_meta( $order->customer_user, 'direct_debit_bic', $bic ); 
  321.  
  322.  
  323. public function add_email_template( $mails ) { 
  324. $mails[ 'WC_GZD_Email_Customer_SEPA_Direct_Debit_Mandate' ] = include WC_germanized()->plugin_path() . '/includes/emails/class-wc-gzd-email-customer-sepa-direct-debit-mandate.php'; 
  325. return $mails; 
  326.  
  327. public function generate_mandate() { 
  328.  
  329. if ( ! $this->is_available() ) 
  330. exit(); 
  331.  
  332. if ( ! isset( $_GET[ '_wpnonce' ] ) || ! wp_verify_nonce( $_GET[ '_wpnonce' ], 'show_direct_debit' ) ) 
  333. exit(); 
  334.  
  335. $params = array( 
  336. 'account_holder' => wc_clean( isset( $_GET[ 'debit_holder' ] ) ? $_GET[ 'debit_holder' ] : '' ),  
  337. 'account_iban' => wc_clean( isset( $_GET[ 'debit_iban' ] ) ? $_GET[ 'debit_iban' ] : '' ),  
  338. 'account_swift' => wc_clean( isset( $_GET[ 'debit_swift' ] ) ? $_GET[ 'debit_swift' ] : '' ),  
  339. 'street' => wc_clean( isset( $_GET[ 'address' ] ) ? $_GET[ 'address' ] : '' ),  
  340. 'postcode' => wc_clean( isset( $_GET[ 'postcode' ] ) ? $_GET[ 'postcode' ] : '' ),  
  341. 'city' => wc_clean( isset( $_GET[ 'city' ] ) ? $_GET[ 'city' ] : '' ),  
  342. 'country' => ( isset( $_GET[ 'country' ] ) && isset( WC()->countries->countries[ $_GET[ 'country' ] ] ) ? WC()->countries->countries[ $_GET[ 'country' ] ] : '' ),  
  343. ); 
  344.  
  345. echo $this->generate_mandate_text( $params ); 
  346. exit(); 
  347.  
  348.  
  349. public function generate_mandate_by_order( $order ) { 
  350.  
  351. if ( is_numeric( $order ) ) 
  352. $order = wc_get_order( absint( $order ) ); 
  353.  
  354. $params = array( 
  355. 'account_holder' => $order->direct_debit_holder,  
  356. 'account_iban' => $this->mask( $this->maybe_decrypt( $order->direct_debit_iban ) ),  
  357. 'account_swift' => $this->maybe_decrypt( $order->direct_debit_bic ),  
  358. 'street' => $order->billing_address_1,  
  359. 'postcode' => $order->billing_postcode,  
  360. 'city' => $order->billing_city,  
  361. 'country' => WC()->countries->countries[ $order->billing_country ],  
  362. 'date' => date_i18n( wc_date_format(), strtotime( $order->post->post_date ) ),  
  363. 'mandate_id' => $this->get_mandate_id( $order->id ),  
  364. ); 
  365.  
  366. return $this->generate_mandate_text( $params ); 
  367.  
  368.  
  369. public function mask( $data ) { 
  370.  
  371. if ( strlen( $data ) <= 4 || $this->get_option( 'mask' ) === 'no' ) 
  372. return $data; 
  373.  
  374. return str_repeat( apply_filters( 'woocommerce_gzd_direct_debit_mask_char', '*' ), strlen( $data ) - 4 ) . substr( $data, -4 ); 
  375.  
  376. public function generate_mandate_text( $args = array() ) { 
  377.  
  378. $args = wp_parse_args( $args, array( 
  379. 'company_info' => $this->company_info,  
  380. 'company_identification_number' => $this->company_identification_number,  
  381. 'date' => date_i18n( wc_date_format(), strtotime( "now" ) ),  
  382. 'mandate_id' => $this->get_mandate_id(),  
  383. ) ); 
  384.  
  385. $text = $this->mandate_text; 
  386.  
  387. foreach ( $args as $key => $val ) 
  388. $text = str_replace( '[' . $key . ']', $val, $text ); 
  389.  
  390. return apply_filters( 'the_content', $text ); 
  391.  
  392.  
  393. public function checkbox() { 
  394.  
  395. if ( $this->is_available() && $this->enable_checkbox === 'yes' ) : ?> 
  396.  
  397. <p class="form-row legal direct-debit-checkbox"> 
  398.  
  399. <input type="checkbox" class="input-checkbox" name="direct_debit_legal" id="direct-debit-checkbox" /> 
  400.  
  401. <label class="checkbox" for="direct-debit-checkbox"> 
  402. <?php echo $this->get_checkbox_label(); ?> 
  403. <a href="" rel="prettyPhoto" id="show-direct-debit-pretty" class="hidden"></a> 
  404. </label> 
  405.  
  406. </p> 
  407.  
  408. <?php endif;  
  409.  
  410. public function get_checkbox_label() { 
  411. $ajax_url = wp_nonce_url( add_query_arg( array( 'action' => 'show_direct_debit' ), admin_url( 'admin-ajax.php' ) ), 'show_direct_debit' ); 
  412. return apply_filters( 'woocommerce_gzd_direct_debit_ajax_url', str_replace( array( '{link}', '{/link}' ), array( '<a href="' . $ajax_url . '" id="show-direct-debit-trigger" rel="prettyPhoto">', '</a>' ), $this->checkbox_label ), $this ); 
  413.  
  414. /** 
  415. * Initialise Gateway Settings Form Fields 
  416. */ 
  417. public function init_form_fields() { 
  418.  
  419. $this->form_fields = array( 
  420. 'enabled' => array( 
  421. 'title' => __( 'Enable/Disable', 'woocommerce-germanized' ),  
  422. 'type' => 'checkbox',  
  423. 'label' => __( 'Enable Direct Debit Payment', 'woocommerce-germanized' ),  
  424. 'default' => 'no' 
  425. ),  
  426. 'title' => array( 
  427. 'title' => _x( 'Title', 'gateway', 'woocommerce-germanized' ),  
  428. 'type' => 'text',  
  429. 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-germanized' ),  
  430. 'default' => __( 'Direct Debit', 'woocommerce-germanized' ),  
  431. 'desc_tip' => true,  
  432. ),  
  433. 'description' => array( 
  434. 'title' => __( 'Description', 'woocommerce-germanized' ),  
  435. 'type' => 'textarea',  
  436. 'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce-germanized' ),  
  437. 'default' => __( 'The order amount will be debited directly from your bank account.', 'woocommerce-germanized' ),  
  438. 'desc_tip' => true,  
  439. ),  
  440. 'instructions' => array( 
  441. 'title' => __( 'Instructions', 'woocommerce-germanized' ),  
  442. 'type' => 'textarea',  
  443. 'description' => __( 'Instructions that will be added to the thank you page and emails.', 'woocommerce-germanized' ),  
  444. 'default' => '',  
  445. 'desc_tip' => true,  
  446. ),  
  447. 'company_info' => array( 
  448. 'title' => __( 'Debtee', 'woocommerce-germanized' ),  
  449. 'type' => 'text',  
  450. 'description' => __( 'Insert your company information.', 'woocommerce-germanized' ),  
  451. 'default' => '',  
  452. 'placeholder' => __( 'Company Inc, John Doe Street, New York', 'woocommerce-germanized' ),  
  453. 'desc_tip' => true,  
  454. ),  
  455. 'company_account_holder' => array( 
  456. 'title' => __( 'Account Holder', 'woocommerce-germanized' ),  
  457. 'type' => 'text',  
  458. 'description' => __( 'Insert the bank account holder name.', 'woocommerce-germanized' ),  
  459. 'default' => '',  
  460. 'placeholder' => __( 'Company Inc', 'woocommerce-germanized' ),  
  461. 'desc_tip' => true,  
  462. ),  
  463. 'company_account_iban' => array( 
  464. 'title' => __( 'IBAN', 'woocommerce-germanized' ),  
  465. 'type' => 'text',  
  466. 'description' => __( 'Insert the bank account IBAN.', 'woocommerce-germanized' ),  
  467. 'default' => '',  
  468. 'desc_tip' => true,  
  469. ),  
  470. 'company_account_bic' => array( 
  471. 'title' => __( 'BIC', 'woocommerce-germanized' ),  
  472. 'type' => 'text',  
  473. 'description' => __( 'Insert the bank account BIC.', 'woocommerce-germanized' ),  
  474. 'default' => '',  
  475. 'desc_tip' => true,  
  476. ),  
  477. 'company_identification_number' => array( 
  478. 'title' => __( 'Debtee identification number', 'woocommerce-germanized' ),  
  479. 'type' => 'text',  
  480. 'description' => sprintf( __( 'Insert your debtee indentification number. More information can be found <a href="%s">here</a>.', 'woocommerce-germanized' ), 'http://www.bundesbank.de/Navigation/DE/Aufgaben/Unbarer_Zahlungsverkehr/SEPA/Glaeubiger_Identifikationsnummer/glaeubiger_identifikationsnummer.html' ),  
  481. 'default' => '',  
  482. ),  
  483. 'generate_mandate_id' => array( 
  484. 'title' => __( 'Generate Mandate ID', 'woocommerce-germanized' ),  
  485. 'type' => 'checkbox',  
  486. 'label' => __( 'Automatically generate Mandate ID.', 'woocommerce-germanized' ),  
  487. 'description' => __( 'Automatically generate Mandate ID after order completion (based on Order ID).', 'woocommerce-germanized' ),  
  488. 'default' => 'yes',  
  489. ),  
  490. 'mandate_id_format' => array( 
  491. 'title' => __( 'Mandate ID Format', 'woocommerce-germanized' ),  
  492. 'type' => 'text',  
  493. 'description' => __( 'You may extend the Mandate ID format by adding a prefix and/or suffix. Use {id} as placeholder to insert the automatically generated ID.', 'woocommerce-germanized' ),  
  494. 'default' => 'MANDAT{id}',  
  495. ),  
  496. 'mandate_text' => array( 
  497. 'title' => __( 'Mandate Text', 'woocommerce-germanized' ),  
  498. 'type' => 'textarea',  
  499. 'description' => __( 'This text will be populated with live order/checkout data. Will be used as preview direct debit mandate and as email template text.', 'woocommerce-germanized' ),  
  500. 'default' => '',  
  501. 'css' => 'min-height: 250px;',  
  502. 'desc_tip' => true,  
  503. ),  
  504. 'enable_checkbox' => array( 
  505. 'title' => __( 'Checkbox', 'woocommerce-germanized' ),  
  506. 'label' => __( 'Enable "agree to SEPA mandate" checkbox', 'woocommerce-germanized' ),  
  507. 'type' => 'checkbox',  
  508. 'description' => __( 'Enable a checkbox linking to a SEPA direct debit mandate preview.', 'woocommerce-germanized' ),  
  509. 'default' => 'yes',  
  510. ),  
  511. 'checkbox_label' => array( 
  512. 'title' => __( 'Checkbox label', 'woocommerce-germanized' ),  
  513. 'type' => 'text',  
  514. 'description' => __( 'Customize the checkbox label. Use {link}link name{/link} to insert the preview link.', 'woocommerce-germanized' ),  
  515. 'default' => __( 'I hereby agree to the {link}direct debit mandate{/link}.', 'woocommerce-germanized' ),  
  516. 'desc_tip' => true,  
  517. ),  
  518. 'mask' => array( 
  519. 'title' => __( 'Mask IBAN', 'woocommerce-germanized' ),  
  520. 'label' => __( 'Mask the IBAN within emails.', 'woocommerce-germanized' ),  
  521. 'type' => 'checkbox',  
  522. 'description' => __( 'This will lead to masked IBANs within emails (replaced by *). All but last 4 digits will be masked.', 'woocommerce-germanized' ),  
  523. 'default' => 'yes',  
  524. ),  
  525.  
  526. ); 
  527.  
  528. if ( $this->supports_encryption() ) { 
  529.  
  530. $this->form_fields = array_merge( $this->form_fields, array( 'remember' => array( 
  531. 'title' => __( 'Remember', 'woocommerce-germanized' ),  
  532. 'label' => __( 'Remember account data for returning customers.', 'woocommerce-germanized' ),  
  533. 'type' => 'checkbox',  
  534. 'description' => __( 'Save account data as user meta if user has/creates a customer account.', 'woocommerce-germanized' ),  
  535. 'default' => 'no',  
  536. ) ) ); 
  537.  
  538.  
  539.  
  540. public function get_user_account_data( $user_id = '' ) { 
  541.  
  542. if ( empty( $user_id ) ) 
  543. $user_id = get_current_user_id(); 
  544.  
  545. $data = array( 
  546. 'holder' => '',  
  547. 'iban' => '',  
  548. 'bic' => '',  
  549. ); 
  550.  
  551. if ( $this->remember !== 'yes' ) 
  552. return $data; 
  553.  
  554. $data = array( 
  555. 'holder' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_holder', true ) ),  
  556. 'iban' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_iban', true ) ),  
  557. 'bic' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_bic', true ) ),  
  558. ); 
  559.  
  560. return $data; 
  561.  
  562. /** 
  563. * Payment form on checkout page 
  564. */ 
  565. public function payment_fields() { 
  566.  
  567. if ( $description = $this->get_description() ) { 
  568. echo wpautop( wptexturize( $description ) ); 
  569.  
  570. $account_data = $this->get_user_account_data(); 
  571.  
  572. $fields = array( 
  573. 'account-holder' => '<p class="form-row form-row-wide"> 
  574. <label for="' . esc_attr( $this->id ) . '-account-holder">' . __( 'Account Holder', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  575. <input id="' . esc_attr( $this->id ) . '-account-holder" class="input-text wc-gzd-' . $this->id . '-account-holder" value="' . esc_attr( $account_data[ 'holder' ] ) . '" type="text" autocomplete="off" placeholder="" name="' . str_replace( '-', '_', $this->id ) . '_account_holder' . '" /> 
  576. </p>',  
  577. 'account-iban' => '<p class="form-row form-row-wide"> 
  578. <label for="' . esc_attr( $this->id ) . '-account-iban">' . __( 'IBAN', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  579. <input id="' . esc_attr( $this->id ) . '-account-iban" class="input-text wc-gzd-' . $this->id . '-account-iban" type="text" value="' . esc_attr( $account_data[ 'iban' ] ) . '" autocomplete="off" placeholder="" name="' . str_replace( '-', '_', $this->id ) . '_account_iban' . '" /> 
  580. </p>',  
  581. 'account-bic' => '<p class="form-row form-row-wide"> 
  582. <label for="' . esc_attr( $this->id ) . '-account-bic">' . __( 'BIC/SWIFT', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  583. <input id="' . esc_attr( $this->id ) . '-account-bic" class="input-text wc-gzd-' . $this->id . '-account-bic" type="text" value="' . esc_attr( $account_data[ 'bic' ] ) . '" autocomplete="off" placeholder="" name="' . str_replace( '-', '_', $this->id ) . '_account_bic' . '" /> 
  584. </p>',  
  585. ); 
  586.  
  587. ?> 
  588. <fieldset id="<?php echo $this->id; ?>-form"> 
  589. <?php do_action( 'woocommerce_gzd_direct_debit_form_start', $this->id ); ?> 
  590. <?php 
  591. foreach ( $fields as $field ) { 
  592. echo $field; 
  593. ?> 
  594. <?php do_action( 'woocommerce_gzd_direct_debit_form_end', $this->id ); ?> 
  595. <div class="clear"></div> 
  596. </fieldset> 
  597. <?php 
  598.  
  599.  
  600. public function validate_fields() {  
  601.  
  602. if ( ! $this->is_available() || ! isset( $_POST[ 'payment_method' ] ) || $_POST[ 'payment_method' ] != $this->id ) 
  603. return; 
  604.  
  605. $iban = ( isset( $_POST[ 'direct_debit_account_iban' ] ) ? wc_clean( $_POST[ 'direct_debit_account_iban' ] ) : '' ); 
  606. $holder = ( isset( $_POST[ 'direct_debit_account_holder' ] ) ? wc_clean( $_POST[ 'direct_debit_account_holder' ] ) : '' ); 
  607. $bic = ( isset( $_POST[ 'direct_debit_account_bic' ] ) ? wc_clean( $_POST[ 'direct_debit_account_bic' ] ) : '' ); 
  608. $country = ( isset( $_POST[ 'billing_country' ] ) ? wc_clean( $_POST[ 'billing_country' ] ) : WC()->countries->get_base_country() ); 
  609.  
  610. if ( empty( $iban ) || empty( $holder ) || empty( $bic ) ) { 
  611. wc_add_notice( __( 'Please insert your SEPA account data.', 'woocommerce-germanized' ), 'error' ); 
  612. return false; 
  613.  
  614. // Validate IBAN 
  615. include_once( WC_germanized()->plugin_path() . '/includes/libraries/iban/oophp-iban.php' ); 
  616.  
  617. $iban_validator = new IBAN( $iban ); 
  618.  
  619. if ( ! $iban_validator->Verify() ) 
  620. wc_add_notice( __( 'Your IBAN seems to be invalid.', 'woocommerce-germanized' ), 'error' ); 
  621. else if ( $iban_validator->Country() != $country ) 
  622. wc_add_notice( __( 'Your IBAN\'s country code doesn*t match with your billing country.', 'woocommerce-germanized' ), 'error' ); 
  623.  
  624. // Validate BIC 
  625. if ( ! preg_match( '/^([a-zA-Z]) {4}([a-zA-Z]) {2}([0-9a-zA-Z]) {2}([0-9a-zA-Z]{3})?$/', $bic ) )  
  626. wc_add_notice( __( 'Your BIC seems to be invalid.', 'woocommerce-germanized' ), 'error' ); 
  627.  
  628. // Make sure that checkbox gets validated if on woocommerce_pay for order page 
  629. if ( isset( $_POST['woocommerce_pay'] ) ) { 
  630. $this->validate_checkbox(); 
  631.  
  632.  
  633. public function validate_checkbox() { 
  634.  
  635. if ( isset( $_POST[ 'payment_method' ] ) && $_POST[ 'payment_method' ] === $this->id && $this->enable_checkbox === 'yes' && ( ! isset( $_POST[ 'direct_debit_legal' ] ) && empty( $_POST[ 'direct_debit_legal' ] ) ) ) 
  636. wc_add_notice( __( 'Please accept the direct debit mandate.', 'woocommerce-germanized' ), 'error' ); 
  637.  
  638.  
  639. /** 
  640. * payment_scripts function. 
  641. * Outputs scripts used for simplify payment 
  642. */ 
  643. public function payment_scripts() { 
  644.  
  645. if ( ! is_checkout() || ! $this->is_available() ) { 
  646. return; 
  647.  
  648. $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; 
  649. $assets_path = str_replace( array( 'http:', 'https:' ), '', WC()->plugin_url() ) . '/assets/'; 
  650.  
  651. // Ensure that prettyPhoto is being loaded 
  652. wp_register_script( 'prettyPhoto_debit', $assets_path . 'js/prettyPhoto/jquery.prettyPhoto' . $suffix . '.js', array( 'jquery' ), '3.1.6', true ); 
  653. wp_enqueue_script( 'prettyPhoto_debit' ); 
  654. wp_register_style( 'woocommerce_prettyPhoto_css_debit', $assets_path . 'css/prettyPhoto.css' ); 
  655. wp_enqueue_style( 'woocommerce_prettyPhoto_css_debit' ); 
  656.  
  657. wp_register_script( 'wc-gzd-iban', WC_germanized()->plugin_url() . '/includes/gateways/direct-debit/assets/js/iban' . $suffix . '.js', array( 'wc-checkout' ), WC_GERMANIZED_VERSION, true ); 
  658. wp_enqueue_script( 'wc-gzd-iban' ); 
  659.  
  660. wp_register_script( 'wc-gzd-direct-debit', WC_germanized()->plugin_url() . '/includes/gateways/direct-debit/assets/js/direct-debit' . $suffix . '.js', array( 'wc-gzd-iban' ), WC_GERMANIZED_VERSION, true ); 
  661. wp_localize_script( 'wc-gzd-direct-debit', 'direct_debit_params', array( 
  662. 'iban' => __( 'IBAN', 'woocommerce-germanized' ),  
  663. 'swift' => __( 'BIC/SWIFT', 'woocommerce-germanized' ),  
  664. 'is_invalid' => __( 'is invalid', 'woocommerce-germanized' ),  
  665. ) ); 
  666. wp_enqueue_script( 'wc-gzd-direct-debit' ); 
  667.  
  668. /** 
  669. * Output for the order received page. 
  670. */ 
  671. public function thankyou_page() { 
  672. if ( $this->instructions ) 
  673. echo wpautop( wptexturize( $this->instructions ) ); 
  674.  
  675. /** 
  676. * Add content to the WC emails. 
  677. * @access public 
  678. * @param WC_Order $order 
  679. * @param bool $sent_to_admin 
  680. * @param bool $plain_text 
  681. */ 
  682. public function email_instructions( $order, $sent_to_admin, $plain_text = false ) { 
  683. if ( $this->instructions && ! $sent_to_admin && 'direct-debit' === $order->payment_method && $order->has_status( 'processing' ) ) { 
  684. echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL; 
  685.  
  686. /** 
  687. * Process the payment and return the result 
  688. * @param int $order_id 
  689. * @return array 
  690. */ 
  691. public function process_payment( $order_id ) { 
  692.  
  693. $order = wc_get_order( $order_id ); 
  694.  
  695. // Mark as on-hold (we're awaiting the cheque) 
  696. $order->update_status( 'processing', __( 'Processing direct debit', 'woocommerce-germanized' ) ); 
  697.  
  698. // Reduce stock levels 
  699. $order->reduce_order_stock(); 
  700.  
  701. // Remove cart 
  702. WC()->cart->empty_cart(); 
  703.  
  704. // Return thankyou redirect 
  705. return array( 
  706. 'result' => 'success',  
  707. 'redirect' => $this->get_return_url( $order ) 
  708. ); 
  709.  
  710. public function maybe_encrypt( $string ) { 
  711. if ( $this->supports_encryption() ) {  
  712. return WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->encrypt( $string ); 
  713. return $string; 
  714.  
  715. public function maybe_decrypt( $string ) { 
  716. if ( $this->supports_encryption() ) { 
  717. $decrypted = WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->decrypt( $string ); 
  718.  
  719. // Maxlength of IBAN is 30 - seems like we have an encrypted string (cannot be decrypted, maybe key changed) 
  720. if ( strlen( $decrypted ) > 40 ) 
  721. return ""; 
  722.  
  723. return $decrypted; 
  724.  
  725. return $string; 
  726.  
  727. public function supports_encryption() { 
  728.  
  729. global $wp_version; 
  730.  
  731. if ( version_compare( phpversion(), '5.4', '<' ) ) 
  732. return false;  
  733. if ( ! extension_loaded( 'openssl' ) ) 
  734. return false; 
  735. if ( version_compare( $wp_version, '4.4', '<' ) ) 
  736. return false; 
  737.  
  738. require_once( 'class-wc-gzd-gateway-direct-debit-encryption-helper.php' ); 
  739.  
  740. if ( ! WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->is_configured() ) 
  741. return false; 
  742.  
  743. return true; 
  744.