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->pain_format = $this->get_option( 'pain_format', 'pain.008.002.02' ); 
  31. $this->checkbox_label = $this->get_option( 'checkbox_label' ); 
  32. $this->remember = $this->get_option( 'remember', 'no' ); 
  33. $this->mask = $this->get_option( 'mask', 'yes' ); 
  34. $this->mandate_text = $this->get_option( 'mandate_text', __( '[company_info] 
  35. debtee identification number: [company_identification_number] 
  36. mandat reference number: [mandate_id]. 
  37.  
  38. <h3>SEPA Direct Debit Mandate</h3> 
  39.  
  40. 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. 
  41.  
  42. 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. 
  43.  
  44. <strong>Debtor:</strong> 
  45. Account holder: [account_holder] 
  46. Street: [street] 
  47. Postcode: [postcode] 
  48. City: [city] 
  49. Country: [country] 
  50. IBAN: [account_iban] 
  51. BIC: [account_swift] 
  52.  
  53. [city], [date], [account_holder] 
  54.  
  55. This letter is done automatically and is valid without signature. 
  56.  
  57. <hr/> 
  58.  
  59. Please notice: Period for pre-information of the SEPA direct debit is shortened to one day.', 'woocommerce-germanized' ) ); 
  60.  
  61. $this->supports = array( 
  62. 'products',  
  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 ( wc_gzd_get_crud_data( $order, 'payment_method' ) === $this->id ) { 
  114. $actions[ 'download-sepa' ] = array( 
  115. 'url' => add_query_arg( array( 'download' => 'true', 'content' => 'sepa', 'sepa_order_id' => wc_gzd_get_crud_data( $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. } elseif ( 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. $msg_id = apply_filters( 'woocommerce_gzd_direct_debit_sepa_xml_msg_id', $this->company_account_bic . '00' . date( 'YmdHis', time() ) ); 
  187. $payment_id = 'PMT-ID-' . date( 'YmdHis', time() ); 
  188.  
  189. $directDebit = Digitick\Sepa\TransferFile\Factory\TransferFileFacadeFactory::createDirectDebit( $msg_id, $this->company_account_holder, $this->pain_format ); 
  190. $directDebit = apply_filters( 'woocommerce_gzd_direct_debit_sepa_xml_exporter', $directDebit ); 
  191.  
  192. $directDebit->addPaymentInfo( $payment_id, array( 
  193. 'id' => $payment_id,  
  194. 'creditorName' => $this->company_account_holder,  
  195. 'creditorAccountIBAN' => $this->clean_whitespaces( $this->company_account_iban ),  
  196. 'creditorAgentBIC' => $this->clean_whitespaces( $this->company_account_bic ),  
  197. 'seqType' => Digitick\Sepa\PaymentInformation::S_ONEOFF,  
  198. 'creditorId' => $this->clean_whitespaces( $this->company_identification_number ),  
  199. )); 
  200.  
  201. while ( $order_query->have_posts() ) { 
  202.  
  203. $order_query->next_post(); 
  204. $order = wc_get_order( $order_query->post->ID ); 
  205.  
  206. // Add a Single Transaction to the named payment 
  207. $directDebit->addTransfer( $payment_id, apply_filters( 'woocommerce_gzd_direct_debit_sepa_xml_exporter_transfer_args', array( 
  208. 'amount' => $order->get_total(),  
  209. 'debtorIban' => $this->clean_whitespaces( $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_iban' ) ) ),  
  210. 'debtorBic' => $this->clean_whitespaces( $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_bic' ) ) ),  
  211. 'debtorName' => wc_gzd_get_crud_data( $order, 'direct_debit_holder' ),  
  212. 'debtorMandate' => $this->get_mandate_id( wc_gzd_get_crud_data( $order, 'id' ) ), date_i18n( "Y-m-d", strtotime( wc_gzd_get_crud_data( $order, 'order_date' ) ) ),  
  213. 'debtorMandateSignDate' => date_i18n( 'd.m.Y', strtotime( wc_gzd_get_crud_data( $order, 'order_date' ) ) ),  
  214. 'remittanceInformation' => apply_filters( 'woocommerce_germanized_direct_debit_purpose', sprintf( __( 'Order %s', 'woocommerce-germanized' ), $order->get_order_number() ), $order ),  
  215. ) ), $this, $order ); 
  216.  
  217. header( 'Content-Description: File Transfer' ); 
  218. header( 'Content-Disposition: attachment; filename=' . $filename ); 
  219. header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true ); 
  220. header( 'Cache-Control: no-cache, no-store, must-revalidate' );  
  221. header( 'Pragma: no-cache' ); 
  222. header( 'Expires: 0' ); 
  223.  
  224. echo $directDebit->asXML(); 
  225. exit(); 
  226.  
  227. }  
  228.  
  229.  
  230. public function get_mandate_id( $order_id = false ) { 
  231.  
  232. if ( ! $order_id ) 
  233. return __( 'Will be notified separately', 'woocommerce-germanized' ); 
  234.  
  235. $order = wc_get_order( $order_id ); 
  236.  
  237. if ( wc_gzd_get_crud_data( $order, 'direct_debit_mandate_id' ) ) 
  238. return wc_gzd_get_crud_data( $order, 'direct_debit_mandate_id' ); 
  239.  
  240. $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 ) : '' ) ); 
  241. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_direct_debit_mandate_id', $mandate_id ); 
  242.  
  243. return $mandate_id; 
  244.  
  245. public function email_sepa( $order, $sent_to_admin, $plain_text ) { 
  246.  
  247. if ( $this->id !== wc_gzd_get_crud_data( $order, 'payment_method' ) ) 
  248. return; 
  249.  
  250. $sepa_fields = array( 
  251. __( 'Account Holder', 'woocommerce-germanized' ) => wc_gzd_get_crud_data( $order, 'direct_debit_holder' ),  
  252. __( 'IBAN', 'woocommerce-germanized' ) => $this->mask( $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_iban' ) ) ),  
  253. __( 'BIC/SWIFT', 'woocommerce-germanized' ) => $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_bic' ) ),  
  254. ); 
  255.  
  256. if ( $sent_to_admin ) { 
  257. $sepa_fields[ __( 'Mandate Reference ID', 'woocommerce-germanized' ) ] = $this->get_mandate_id( wc_gzd_get_crud_data( $order, 'id' ) ); 
  258.  
  259. wc_get_template( 'emails/email-sepa-data.php', array( 'fields' => $sepa_fields ) ); 
  260.  
  261.  
  262. public function set_debit_fields( $fields ) { 
  263.  
  264. global $post; 
  265.  
  266. $order = wc_get_order( $post->ID ); 
  267.  
  268. if ( wc_gzd_get_crud_data( $order, 'payment_method' ) !== $this->id ) 
  269. return $fields; 
  270.  
  271. $fields[ 'direct_debit_holder' ] = array( 
  272. 'label' => __( 'Account Holder', 'woocommerce-germanized' ),  
  273. 'id' => '_direct_debit_holder',  
  274. 'class' => '',  
  275. 'show' => false,  
  276. ); 
  277.  
  278. $fields[ 'direct_debit_iban' ] = array( 
  279. 'label' => __( 'IBAN', 'woocommerce-germanized' ),  
  280. 'id' => '_direct_debit_iban',  
  281. 'value' => $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_iban' ) ),  
  282. 'show' => false,  
  283. ); 
  284.  
  285. $fields[ 'direct_debit_bic' ] = array( 
  286. 'label' => __( 'BIC/SWIFT', 'woocommerce-germanized' ),  
  287. 'id' => '_direct_debit_bic',  
  288. 'value' => $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_bic' ) ),  
  289. 'show' => false,  
  290. ); 
  291.  
  292. $fields[ 'direct_debit_mandate_id' ] = array( 
  293. 'label' => __( 'Mandate Reference ID', 'woocommerce-germanized' ),  
  294. 'id' => '_direct_debit_mandate_id',  
  295. 'show' => false,  
  296. ); 
  297.  
  298. return $fields; 
  299.  
  300.  
  301. public function send_mail( $order_id ) { 
  302.  
  303. $order = wc_get_order( $order_id ); 
  304.  
  305. if ( wc_gzd_get_crud_data( $order, 'payment_method' ) == $this->id ) { 
  306. if ( $mail = WC_germanized()->emails->get_email_instance_by_id( 'customer_sepa_direct_debit_mandate' ) ) 
  307. $mail->trigger( $order ); 
  308.  
  309.  
  310. public function clean_whitespaces( $str ) { 
  311. return preg_replace('/\s+/', '', $str ); 
  312.  
  313. public function set_order_meta( $order_id, $posted ) { 
  314.  
  315. $order = wc_get_order( $order_id ); 
  316.  
  317. if ( ! ( wc_gzd_get_crud_data( $order, 'payment_method' ) === $this->id ) ) 
  318. return; 
  319.  
  320. $holder = ( isset( $_POST[ 'direct_debit_account_holder' ] ) ? wc_clean( $_POST[ 'direct_debit_account_holder' ] ) : '' ); 
  321. $iban = ( isset( $_POST[ 'direct_debit_account_iban' ] ) ? $this->maybe_encrypt( $this->clean_whitespaces( wc_clean( $_POST[ 'direct_debit_account_iban' ] ) ) ) : '' ); 
  322. $bic = ( isset( $_POST[ 'direct_debit_account_bic' ] ) ? $this->maybe_encrypt( $this->clean_whitespaces( wc_clean( $_POST[ 'direct_debit_account_bic' ] ) ) ) : '' ); 
  323.  
  324. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_direct_debit_holder', $holder ); 
  325. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_direct_debit_iban', $iban ); 
  326. update_post_meta( wc_gzd_get_crud_data( $order, 'id' ), '_direct_debit_bic', $bic ); 
  327.  
  328. if ( ! $this->supports_encryption() || $this->remember === 'no' || ! wc_gzd_get_crud_data( $order, 'user_id' ) ) 
  329. return; 
  330.  
  331. update_user_meta( wc_gzd_get_crud_data( $order, 'user_id' ), 'direct_debit_holder', $holder ); 
  332. update_user_meta( wc_gzd_get_crud_data( $order, 'user_id' ), 'direct_debit_iban', $iban ); 
  333. update_user_meta( wc_gzd_get_crud_data( $order, 'user_id' ), 'direct_debit_bic', $bic ); 
  334.  
  335.  
  336. public function add_email_template( $mails ) { 
  337. $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'; 
  338. return $mails; 
  339.  
  340. public function generate_mandate() { 
  341.  
  342. if ( ! $this->is_available() ) 
  343. exit(); 
  344.  
  345. if ( ! isset( $_GET[ '_wpnonce' ] ) || ! wp_verify_nonce( $_GET[ '_wpnonce' ], 'show_direct_debit' ) ) 
  346. exit(); 
  347.  
  348. $params = array( 
  349. 'account_holder' => wc_clean( isset( $_GET[ 'debit_holder' ] ) ? $_GET[ 'debit_holder' ] : '' ),  
  350. 'account_iban' => wc_clean( isset( $_GET[ 'debit_iban' ] ) ? $_GET[ 'debit_iban' ] : '' ),  
  351. 'account_swift' => wc_clean( isset( $_GET[ 'debit_swift' ] ) ? $_GET[ 'debit_swift' ] : '' ),  
  352. 'street' => wc_clean( isset( $_GET[ 'address' ] ) ? $_GET[ 'address' ] : '' ),  
  353. 'postcode' => wc_clean( isset( $_GET[ 'postcode' ] ) ? $_GET[ 'postcode' ] : '' ),  
  354. 'city' => wc_clean( isset( $_GET[ 'city' ] ) ? $_GET[ 'city' ] : '' ),  
  355. 'country' => ( isset( $_GET[ 'country' ] ) && isset( WC()->countries->countries[ $_GET[ 'country' ] ] ) ? WC()->countries->countries[ $_GET[ 'country' ] ] : '' ),  
  356. ); 
  357.  
  358. echo $this->generate_mandate_text( $params ); 
  359. exit(); 
  360.  
  361.  
  362. public function generate_mandate_by_order( $order ) { 
  363.  
  364. if ( is_numeric( $order ) ) 
  365. $order = wc_get_order( absint( $order ) ); 
  366.  
  367. $params = array( 
  368. 'account_holder' => wc_gzd_get_crud_data( $order, 'direct_debit_holder' ),  
  369. 'account_iban' => $this->mask( $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_iban' ) ) ),  
  370. 'account_swift' => $this->maybe_decrypt( wc_gzd_get_crud_data( $order, 'direct_debit_bic' ) ),  
  371. 'street' => wc_gzd_get_crud_data( $order, 'billing_address_1' ),  
  372. 'postcode' => wc_gzd_get_crud_data( $order, 'billing_postcode' ),  
  373. 'city' => wc_gzd_get_crud_data( $order, 'billing_city' ),  
  374. 'country' => WC()->countries->countries[ wc_gzd_get_crud_data( $order, 'billing_country' ) ],  
  375. 'date' => date_i18n( wc_date_format(), strtotime( wc_gzd_get_crud_data( $order, 'order_date' ) ) ),  
  376. 'mandate_id' => $this->get_mandate_id( wc_gzd_get_crud_data( $order, 'id' ) ),  
  377. ); 
  378.  
  379. return $this->generate_mandate_text( $params ); 
  380.  
  381.  
  382. public function mask( $data ) { 
  383.  
  384. if ( strlen( $data ) <= 4 || $this->get_option( 'mask' ) === 'no' ) 
  385. return $data; 
  386.  
  387. return str_repeat( apply_filters( 'woocommerce_gzd_direct_debit_mask_char', '*' ), strlen( $data ) - 4 ) . substr( $data, -4 ); 
  388.  
  389. public function generate_mandate_text( $args = array() ) { 
  390.  
  391. $args = wp_parse_args( $args, array( 
  392. 'company_info' => $this->company_info,  
  393. 'company_identification_number' => $this->company_identification_number,  
  394. 'date' => date_i18n( wc_date_format(), strtotime( "now" ) ),  
  395. 'mandate_id' => $this->get_mandate_id(),  
  396. ) ); 
  397.  
  398. $text = $this->mandate_text; 
  399.  
  400. foreach ( $args as $key => $val ) 
  401. $text = str_replace( '[' . $key . ']', $val, $text ); 
  402.  
  403. return apply_filters( 'the_content', $text ); 
  404.  
  405.  
  406. public function checkbox() { 
  407.  
  408. if ( $this->is_available() && $this->enable_checkbox === 'yes' ) : ?> 
  409.  
  410. <p class="form-row legal direct-debit-checkbox"> 
  411.  
  412. <input type="checkbox" class="input-checkbox" name="direct_debit_legal" id="direct-debit-checkbox" /> 
  413.  
  414. <label class="checkbox" for="direct-debit-checkbox"> 
  415. <?php echo $this->get_checkbox_label(); ?> 
  416. <a href="" rel="prettyPhoto" id="show-direct-debit-pretty" class="hidden"></a> 
  417. </label> 
  418.  
  419. </p> 
  420.  
  421. <?php endif;  
  422.  
  423. public function get_checkbox_label() { 
  424. $ajax_url = wp_nonce_url( add_query_arg( array( 'action' => 'show_direct_debit' ), admin_url( 'admin-ajax.php' ) ), 'show_direct_debit' ); 
  425. 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 ); 
  426.  
  427. /** 
  428. * Initialise Gateway Settings Form Fields 
  429. */ 
  430. public function init_form_fields() { 
  431.  
  432. $this->form_fields = array( 
  433. 'enabled' => array( 
  434. 'title' => __( 'Enable/Disable', 'woocommerce-germanized' ),  
  435. 'type' => 'checkbox',  
  436. 'label' => __( 'Enable Direct Debit Payment', 'woocommerce-germanized' ),  
  437. 'default' => 'no' 
  438. ),  
  439. 'title' => array( 
  440. 'title' => _x( 'Title', 'gateway', 'woocommerce-germanized' ),  
  441. 'type' => 'text',  
  442. 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-germanized' ),  
  443. 'default' => __( 'Direct Debit', 'woocommerce-germanized' ),  
  444. 'desc_tip' => true,  
  445. ),  
  446. 'description' => array( 
  447. 'title' => __( 'Description', 'woocommerce-germanized' ),  
  448. 'type' => 'textarea',  
  449. 'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce-germanized' ),  
  450. 'default' => __( 'The order amount will be debited directly from your bank account.', 'woocommerce-germanized' ),  
  451. 'desc_tip' => true,  
  452. ),  
  453. 'instructions' => array( 
  454. 'title' => __( 'Instructions', 'woocommerce-germanized' ),  
  455. 'type' => 'textarea',  
  456. 'description' => __( 'Instructions that will be added to the thank you page and emails.', 'woocommerce-germanized' ),  
  457. 'default' => '',  
  458. 'desc_tip' => true,  
  459. ),  
  460. 'company_info' => array( 
  461. 'title' => __( 'Debtee', 'woocommerce-germanized' ),  
  462. 'type' => 'text',  
  463. 'description' => __( 'Insert your company information.', 'woocommerce-germanized' ),  
  464. 'default' => '',  
  465. 'placeholder' => __( 'Company Inc, John Doe Street, New York', 'woocommerce-germanized' ),  
  466. 'desc_tip' => true,  
  467. ),  
  468. 'company_account_holder' => array( 
  469. 'title' => __( 'Account Holder', 'woocommerce-germanized' ),  
  470. 'type' => 'text',  
  471. 'description' => __( 'Insert the bank account holder name.', 'woocommerce-germanized' ),  
  472. 'default' => '',  
  473. 'placeholder' => __( 'Company Inc', 'woocommerce-germanized' ),  
  474. 'desc_tip' => true,  
  475. ),  
  476. 'company_account_iban' => array( 
  477. 'title' => __( 'IBAN', 'woocommerce-germanized' ),  
  478. 'type' => 'text',  
  479. 'description' => __( 'Insert the bank account IBAN.', 'woocommerce-germanized' ),  
  480. 'default' => '',  
  481. 'desc_tip' => true,  
  482. ),  
  483. 'company_account_bic' => array( 
  484. 'title' => __( 'BIC', 'woocommerce-germanized' ),  
  485. 'type' => 'text',  
  486. 'description' => __( 'Insert the bank account BIC.', 'woocommerce-germanized' ),  
  487. 'default' => '',  
  488. 'desc_tip' => true,  
  489. ),  
  490. 'company_identification_number' => array( 
  491. 'title' => __( 'Debtee identification number', 'woocommerce-germanized' ),  
  492. 'type' => 'text',  
  493. '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' ),  
  494. 'default' => '',  
  495. ),  
  496. 'generate_mandate_id' => array( 
  497. 'title' => __( 'Generate Mandate ID', 'woocommerce-germanized' ),  
  498. 'type' => 'checkbox',  
  499. 'label' => __( 'Automatically generate Mandate ID.', 'woocommerce-germanized' ),  
  500. 'description' => __( 'Automatically generate Mandate ID after order completion (based on Order ID).', 'woocommerce-germanized' ),  
  501. 'default' => 'yes',  
  502. ),  
  503. 'pain_format' => array( 
  504. 'title' => __( 'XML Pain Format', 'woocommerce-germanized' ),  
  505. 'type' => 'text',  
  506. 'description' => __( 'You may adjust the XML Export Pain Schema to your banks needs. Some banks may require pain.001.003.03.', 'woocommerce-germanized' ),  
  507. 'default' => 'pain.008.002.02',  
  508. ),  
  509. 'mandate_id_format' => array( 
  510. 'title' => __( 'Mandate ID Format', 'woocommerce-germanized' ),  
  511. 'type' => 'text',  
  512. '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' ),  
  513. 'default' => 'MANDAT{id}',  
  514. ),  
  515. 'mandate_text' => array( 
  516. 'title' => __( 'Mandate Text', 'woocommerce-germanized' ),  
  517. 'type' => 'textarea',  
  518. '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' ),  
  519. 'default' => '',  
  520. 'css' => 'min-height: 250px;',  
  521. 'desc_tip' => true,  
  522. ),  
  523. 'enable_checkbox' => array( 
  524. 'title' => __( 'Checkbox', 'woocommerce-germanized' ),  
  525. 'label' => __( 'Enable "agree to SEPA mandate" checkbox', 'woocommerce-germanized' ),  
  526. 'type' => 'checkbox',  
  527. 'description' => __( 'Enable a checkbox linking to a SEPA direct debit mandate preview.', 'woocommerce-germanized' ),  
  528. 'default' => 'yes',  
  529. ),  
  530. 'checkbox_label' => array( 
  531. 'title' => __( 'Checkbox label', 'woocommerce-germanized' ),  
  532. 'type' => 'text',  
  533. 'description' => __( 'Customize the checkbox label. Use {link}link name{/link} to insert the preview link.', 'woocommerce-germanized' ),  
  534. 'default' => __( 'I hereby agree to the {link}direct debit mandate{/link}.', 'woocommerce-germanized' ),  
  535. 'desc_tip' => true,  
  536. ),  
  537. 'mask' => array( 
  538. 'title' => __( 'Mask IBAN', 'woocommerce-germanized' ),  
  539. 'label' => __( 'Mask the IBAN within emails.', 'woocommerce-germanized' ),  
  540. 'type' => 'checkbox',  
  541. 'description' => __( 'This will lead to masked IBANs within emails (replaced by *). All but last 4 digits will be masked.', 'woocommerce-germanized' ),  
  542. 'default' => 'yes',  
  543. ),  
  544.  
  545. ); 
  546.  
  547. if ( $this->supports_encryption() ) { 
  548.  
  549. $this->form_fields = array_merge( $this->form_fields, array( 'remember' => array( 
  550. 'title' => __( 'Remember', 'woocommerce-germanized' ),  
  551. 'label' => __( 'Remember account data for returning customers.', 'woocommerce-germanized' ),  
  552. 'type' => 'checkbox',  
  553. 'description' => __( 'Save account data as user meta if user has/creates a customer account.', 'woocommerce-germanized' ),  
  554. 'default' => 'no',  
  555. ) ) ); 
  556.  
  557.  
  558.  
  559. public function get_user_account_data( $user_id = '' ) { 
  560.  
  561. if ( empty( $user_id ) ) 
  562. $user_id = get_current_user_id(); 
  563.  
  564. $data = array( 
  565. 'holder' => '',  
  566. 'iban' => '',  
  567. 'bic' => '',  
  568. ); 
  569.  
  570. if ( $this->remember !== 'yes' ) 
  571. return $data; 
  572.  
  573. $data = array( 
  574. 'holder' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_holder', true ) ),  
  575. 'iban' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_iban', true ) ),  
  576. 'bic' => $this->maybe_decrypt( get_user_meta( $user_id, 'direct_debit_bic', true ) ),  
  577. ); 
  578.  
  579. return $data; 
  580.  
  581. /** 
  582. * Payment form on checkout page 
  583. */ 
  584. public function payment_fields() { 
  585.  
  586. if ( $description = $this->get_description() ) { 
  587. echo wpautop( wptexturize( $description ) ); 
  588.  
  589. $account_data = $this->get_user_account_data(); 
  590.  
  591. $fields = array( 
  592. 'account-holder' => '<p class="form-row form-row-wide"> 
  593. <label for="' . esc_attr( $this->id ) . '-account-holder">' . __( 'Account Holder', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  594. <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' . '" /> 
  595. </p>',  
  596. 'account-iban' => '<p class="form-row form-row-wide"> 
  597. <label for="' . esc_attr( $this->id ) . '-account-iban">' . __( 'IBAN', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  598. <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' . '" /> 
  599. </p>',  
  600. 'account-bic' => '<p class="form-row form-row-wide"> 
  601. <label for="' . esc_attr( $this->id ) . '-account-bic">' . __( 'BIC/SWIFT', 'woocommerce-germanized' ) . ' <span class="required">*</span></label> 
  602. <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' . '" /> 
  603. </p>',  
  604. ); 
  605.  
  606. ?> 
  607. <fieldset id="<?php echo $this->id; ?>-form"> 
  608. <?php do_action( 'woocommerce_gzd_direct_debit_form_start', $this->id ); ?> 
  609. <?php 
  610. foreach ( $fields as $field ) { 
  611. echo $field; 
  612. ?> 
  613. <?php do_action( 'woocommerce_gzd_direct_debit_form_end', $this->id ); ?> 
  614. <div class="clear"></div> 
  615. </fieldset> 
  616. <?php 
  617.  
  618.  
  619. public function validate_fields() {  
  620.  
  621. if ( ! $this->is_available() || ! isset( $_POST[ 'payment_method' ] ) || $_POST[ 'payment_method' ] != $this->id ) 
  622. return; 
  623.  
  624. $iban = ( isset( $_POST[ 'direct_debit_account_iban' ] ) ? wc_clean( $_POST[ 'direct_debit_account_iban' ] ) : '' ); 
  625. $holder = ( isset( $_POST[ 'direct_debit_account_holder' ] ) ? wc_clean( $_POST[ 'direct_debit_account_holder' ] ) : '' ); 
  626. $bic = ( isset( $_POST[ 'direct_debit_account_bic' ] ) ? wc_clean( $_POST[ 'direct_debit_account_bic' ] ) : '' ); 
  627. $country = ( isset( $_POST[ 'billing_country' ] ) ? wc_clean( $_POST[ 'billing_country' ] ) : WC()->countries->get_base_country() ); 
  628.  
  629. if ( empty( $iban ) || empty( $holder ) || empty( $bic ) ) { 
  630. wc_add_notice( __( 'Please insert your SEPA account data.', 'woocommerce-germanized' ), 'error' ); 
  631. return false; 
  632.  
  633. // Validate IBAN 
  634. include_once( WC_germanized()->plugin_path() . '/includes/libraries/iban/oophp-iban.php' ); 
  635.  
  636. $iban_validator = new IBAN( $iban ); 
  637.  
  638. if ( ! $iban_validator->Verify() ) 
  639. wc_add_notice( __( 'Your IBAN seems to be invalid.', 'woocommerce-germanized' ), 'error' ); 
  640. else if ( $iban_validator->Country() != $country ) 
  641. wc_add_notice( __( 'Your IBAN\'s country code doesn*t match with your billing country.', 'woocommerce-germanized' ), 'error' ); 
  642.  
  643. // Validate BIC 
  644. if ( ! preg_match( '/^([a-zA-Z]) {4}([a-zA-Z]) {2}([0-9a-zA-Z]) {2}([0-9a-zA-Z]{3})?$/', $bic ) )  
  645. wc_add_notice( __( 'Your BIC seems to be invalid.', 'woocommerce-germanized' ), 'error' ); 
  646.  
  647. // Make sure that checkbox gets validated if on woocommerce_pay for order page 
  648. if ( isset( $_POST['woocommerce_pay'] ) ) { 
  649. $this->validate_checkbox(); 
  650.  
  651.  
  652. public function validate_checkbox() { 
  653.  
  654. if ( isset( $_POST[ 'payment_method' ] ) && $_POST[ 'payment_method' ] === $this->id && $this->enable_checkbox === 'yes' && ( ! isset( $_POST[ 'direct_debit_legal' ] ) && empty( $_POST[ 'direct_debit_legal' ] ) ) ) 
  655. wc_add_notice( __( 'Please accept the direct debit mandate.', 'woocommerce-germanized' ), 'error' ); 
  656.  
  657.  
  658. /** 
  659. * payment_scripts function. 
  660. * Outputs scripts used for simplify payment 
  661. */ 
  662. public function payment_scripts() { 
  663.  
  664. if ( ! is_checkout() || ! $this->is_available() ) { 
  665. return; 
  666.  
  667. $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; 
  668. $assets_path = str_replace( array( 'http:', 'https:' ), '', WC()->plugin_url() ) . '/assets/'; 
  669.  
  670. // Ensure that prettyPhoto is being loaded 
  671. wp_register_script( 'prettyPhoto_debit', $assets_path . 'js/prettyPhoto/jquery.prettyPhoto' . $suffix . '.js', array( 'jquery' ), '3.1.6', true ); 
  672. wp_enqueue_script( 'prettyPhoto_debit' ); 
  673. wp_register_style( 'woocommerce_prettyPhoto_css_debit', $assets_path . 'css/prettyPhoto.css' ); 
  674. wp_enqueue_style( 'woocommerce_prettyPhoto_css_debit' ); 
  675.  
  676. 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 ); 
  677. wp_enqueue_script( 'wc-gzd-iban' ); 
  678.  
  679. 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 ); 
  680. wp_localize_script( 'wc-gzd-direct-debit', 'direct_debit_params', array( 
  681. 'iban' => __( 'IBAN', 'woocommerce-germanized' ),  
  682. 'swift' => __( 'BIC/SWIFT', 'woocommerce-germanized' ),  
  683. 'is_invalid' => __( 'is invalid', 'woocommerce-germanized' ),  
  684. ) ); 
  685. wp_enqueue_script( 'wc-gzd-direct-debit' ); 
  686.  
  687. /** 
  688. * Output for the order received page. 
  689. */ 
  690. public function thankyou_page() { 
  691. if ( $this->instructions ) 
  692. echo wpautop( wptexturize( $this->instructions ) ); 
  693.  
  694. /** 
  695. * Add content to the WC emails. 
  696. * @access public 
  697. * @param WC_Order $order 
  698. * @param bool $sent_to_admin 
  699. * @param bool $plain_text 
  700. */ 
  701. public function email_instructions( $order, $sent_to_admin, $plain_text = false ) { 
  702. if ( $this->instructions && ! $sent_to_admin && 'direct-debit' === wc_gzd_get_crud_data( $order, 'payment_method' ) && $order->has_status( 'processing' ) ) { 
  703. echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL; 
  704.  
  705. /** 
  706. * Process the payment and return the result 
  707. * @param int $order_id 
  708. * @return array 
  709. */ 
  710. public function process_payment( $order_id ) { 
  711.  
  712. $order = wc_get_order( $order_id ); 
  713.  
  714. // Mark as on-hold (we're awaiting the cheque) 
  715. $order->update_status( 'on-hold', __( 'Awaiting Direct Debit Payment', 'woocommerce-germanized' ) ); 
  716.  
  717. // Reduce stock level 
  718. wc_gzd_reduce_order_stock( $order_id ); 
  719.  
  720. // Check if cart instance exists (frontend request only) 
  721. if ( WC()->cart ) { 
  722. // Remove cart 
  723. WC()->cart->empty_cart(); 
  724.  
  725. // Return thankyou redirect 
  726. return array( 
  727. 'result' => 'success',  
  728. 'redirect' => $this->get_return_url( $order ) 
  729. ); 
  730.  
  731. public function maybe_encrypt( $string ) { 
  732. if ( $this->supports_encryption() ) {  
  733. return WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->encrypt( $string ); 
  734. return $string; 
  735.  
  736. public function maybe_decrypt( $string ) { 
  737. if ( $this->supports_encryption() ) { 
  738. $decrypted = WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->decrypt( $string ); 
  739.  
  740. // Maxlength of IBAN is 30 - seems like we have an encrypted string (cannot be decrypted, maybe key changed) 
  741. if ( strlen( $decrypted ) > 40 ) 
  742. return ""; 
  743.  
  744. return $decrypted; 
  745.  
  746. return $string; 
  747.  
  748. public function supports_encryption() { 
  749.  
  750. global $wp_version; 
  751.  
  752. if ( version_compare( phpversion(), '5.4', '<' ) ) 
  753. return false;  
  754. if ( ! extension_loaded( 'openssl' ) ) 
  755. return false; 
  756. if ( version_compare( $wp_version, '4.4', '<' ) ) 
  757. return false; 
  758.  
  759. require_once( 'class-wc-gzd-gateway-direct-debit-encryption-helper.php' ); 
  760.  
  761. if ( ! WC_GZD_Gateway_Direct_Debit_Encryption_Helper::instance()->is_configured() ) 
  762. return false; 
  763.  
  764. return true; 
  765.