wcchainpay_init

The WooCommerce ChainPay wcchainpay init function.

Description

wcchainpay_init(); 

Usage

  1. if ( !function_exists( 'wcchainpay_init' ) ) { 
  2. require_once ABSPATH . PLUGINDIR . 'woocommerce-chainpay/woocommerce-chainpay.php'; 
  3.  
  4.  
  5. // NOTICE! Understand what this does before running. 
  6. $result = wcchainpay_init(); 
  7.  

Defined (1)

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

/woocommerce-chainpay.php  
  1. function wcchainpay_init() { 
  2.  
  3. // If we cannot find the WC_Payment_Gateway class we inherit from. 
  4. if ( ! class_exists( 'WC_Payment_Gateway' ) ) { 
  5. // Add the WooCommerce required notice to the admin console. 
  6. return; 
  7.  
  8. // Notify Wordpress about our languages. 
  9. load_plugin_textdomain( 'wcchainpay', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); 
  10.  
  11.  
  12. // Add ChainPay to the list of supported Payment Gateways. 
  13. add_filter( 'woocommerce_payment_gateways', 'wcchainpay_add' ); 
  14.  
  15. function wcchainpay_add( $methods ) { 
  16. $methods[] = 'WC_ChainPay'; 
  17. return $methods; 
  18.  
  19. // ChainPay Class 
  20. class WC_ChainPay extends WC_Payment_Gateway { 
  21.  
  22. public function __construct() { 
  23. global $woocommerce; 
  24.  
  25. $this->id = 'chainpay'; 
  26. $this->icon = plugins_url( 'images/BC_Logotype.png', __FILE__ ); 
  27. $this->has_fields = false; 
  28. $this->method_title = __( 'ChainPay', 'wcchainpay' ); 
  29. $this->method_description = __( 'Bitcoin Payment Gateway', 'wcchainpay' ); 
  30.  
  31. $this->init_form_fields(); 
  32. $this->init_settings(); 
  33.  
  34. $this->title = $this->get_option('title'); 
  35. $this->description = $this->get_option('description'); 
  36. $this->apiKey = $this->get_option('apiKey'); 
  37. $this->privateKey = $this->get_option('privateKey'); 
  38. $this->test = $this->get_option('test'); 
  39.  
  40. if($this->test === 'yes') 
  41. $this->apiAbsoluteUri = 'https://testapi.chainpay.com/'; 
  42. $this->paymentUri = 'https://testpay.chainpay.com/invoice?id='; 
  43. else 
  44. $this->apiAbsoluteUri = 'https://api.chainpay.com/'; 
  45. $this->paymentUri = 'https://pay.chainpay.com/invoice?id='; 
  46. $this->createInvoiceUri = 'invoice'; 
  47.  
  48. $this->log = new WC_Logger(); 
  49. $this->debug = true; 
  50.  
  51. add_action( 'woocommerce_api_wc_chainpay', array( &$this, 'ChainPay_Callback' ) ); 
  52. add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); 
  53.  
  54. if (empty($this->apiKey)) { 
  55. add_action( 'admin_notices', array( &$this, 'ChainPay_MissingApiKey' ) ); 
  56. if (empty( $this->privateKey)) { 
  57. add_action( 'admin_notices', array( &$this, 'ChainPay_MissingPrivateKey' ) ); 
  58.  
  59. public function init_form_fields() { 
  60. $this->form_fields = array( 
  61. 'enabled' => array( 
  62. 'title' => __( 'Enable/Disable', 'wcchainpay' ),  
  63. 'type' => 'checkbox',  
  64. 'label' => __( 'Enable payment with ChainPay', 'wcchainpay' ),  
  65. 'default' => 'yes' 
  66. ),  
  67. 'title' => array( 
  68. 'title' => __( 'Title', 'woocommerce' ),  
  69. 'type' => 'text',  
  70. 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),  
  71. 'default' => __( 'Bitcoin', 'wcchainpay' ),  
  72. 'desc_tip' => true,  
  73. ),  
  74. 'description' => array( 
  75. 'title' => __( 'Description', 'woocommerce' ),  
  76. 'type' => 'textarea',  
  77. 'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),  
  78. 'default' => __( 'Make payment quickly and easily with Bitcoin.', 'wcchainpay' ),  
  79. 'desc_tip' => true,  
  80. ),  
  81. 'apiKey' => array( 
  82. 'title' => __( 'API Key', 'wcchainpay' ),  
  83. 'type' => 'text',  
  84. 'description' => __( 'Your API Key from the ChainPay Portal (Settings Tab).', 'wcchainpay' ),  
  85. 'desc_tip' => true,  
  86. ),  
  87. 'privateKey' => array( 
  88. 'title' => __( 'Private Key', 'wcchainpay' ),  
  89. 'type' => 'text',  
  90. 'description' => __( 'Your Private Key from the ChainPay Portal.', 'wcchainpay' ),  
  91. 'desc_tip' => true,  
  92. ),  
  93. 'test' => array( 
  94. 'title' => __( 'Sandbox', 'wcchainpay' ),  
  95. 'type' => 'checkbox',  
  96. 'label' => __( 'Connect to the Sandbox ChainPay API for testing.', 'wcchainpay' ),  
  97. 'default' => 'no' 
  98. ),  
  99. 'debug' => array( 
  100. 'title' => __( 'Debug Mode', 'wcchainpay' ),  
  101. 'type' => 'checkbox',  
  102. 'label' => __( 'Log communication with the ChainPay API to the WooCommerce logs.', 'wcchainpay' ),  
  103. 'default' => 'no' 
  104. )); 
  105.  
  106. public function process_payment( $order_id ) { 
  107.  
  108. $order = new WC_Order( $order_id ); 
  109.  
  110. // Set the order as pending as we are awaiting payment. 
  111. $order->update_status( 'pending', __( 'Awaiting Bitcoin payment', 'wcchainpay' ) ); 
  112.  
  113. // Call the ChainPay API to create a Invoice. 
  114. $invoice = $this->ChainPay_CreateInvoice($order); 
  115. if($invoice) 
  116. // Store the ChainPay invoice id on the order. 
  117. update_post_meta($order->id, 'chainpay_invoice_id', $invoice->Id); 
  118.  
  119. // Empty shopping cart. 
  120. WC()->cart->empty_cart(); 
  121.  
  122. // Forward to chainpay for payment. 
  123. return array( 
  124. 'result' => 'success',  
  125. 'redirect' => $this->paymentUri . $invoice->Id 
  126. ); 
  127. else 
  128.  
  129.  
  130.  
  131. private function ChainPay_CreateInvoice($order) 
  132. $params = array( 
  133. 'Reference' => $order->id,  
  134. 'RequestCurrency' => get_woocommerce_currency(),  
  135. 'RequestAmount' => (float) $order->order_total,  
  136. 'ForwardOnPaidUri' => $this->get_return_url( $order ),  
  137. 'ForwardOnCancelUri' => htmlspecialchars_decode($order->get_cancel_order_url()),  
  138. 'CallbackUri' => add_query_arg( 'wc-api', 'WC_ChainPay', home_url( '/' ) ),  
  139. 'Metadata' => array( 
  140. 'PayerName' => $order->billing_first_name.' '.$order->billing_last_name,  
  141. 'PayerEmail' => $order->billing_email 
  142. ); 
  143.  
  144. $invoice = $this->ChainPay_Post($params, $this->createInvoiceUri); 
  145.  
  146. if(!$invoice && $this->debug) 
  147. $this->log->add('ChainPay', 'Could not create invoice.'); 
  148.  
  149. return $invoice; 
  150.  
  151. private function ChainPay_Post($params, $relativeUri) 
  152. $postdata = json_encode( $params ); 
  153. $httpArgs = array( 
  154. 'body' => $postdata,  
  155. 'sslverify' => true,  
  156. 'timeout' => 30,  
  157. 'method' => 'POST',  
  158. 'headers' => array ( 
  159. 'Authorization' => $this->apiKey,  
  160. 'Content-Type' => 'application/json' 
  161. ); 
  162.  
  163. $absoluteUri = $this->apiAbsoluteUri . $relativeUri . '.json'; 
  164. $response = wp_remote_post($absoluteUri, $httpArgs); 
  165.  
  166. if ( ! is_wp_error( $response ) && 200 == $response['response']['code'] ) { 
  167. $data = $response['body']; 
  168. $result = $this->ChainPay_DecodeResponse($data); 
  169. if($result) 
  170. if($this->debug) 
  171. $this->log->add('ChainPay', 'Successful call to ChainPay API: ' . $absoluteUri); 
  172. return $result; 
  173.  
  174. $this->log->add('ChainPay', 'Could not deserialize response: ' . $data); 
  175. else if( is_wp_error ($response) ) 
  176. $this->log->add('ChainPay', 'WP Error on call: ' . json_encode($response)); 
  177. else { 
  178. if(401 == $response['response']['code'])  
  179. $this->log->add('ChainPay', 'Unauthorized: Called ChainPay with invalid API Key. Please check your API Key in the WooCommerce checkout settings.'); 
  180. else 
  181. $this->log->add('ChainPay', 'Error returned from ChainPay API. Called URI: ' . $absoluteUri 
  182. . '"\r\nWith data: ' . json_encode($postdata)  
  183. . '\r\nResponse:' . json_encode($response)); 
  184.  
  185. return false; 
  186.  
  187. private function ChainPay_DecodeResponse($data) 
  188. $response = json_decode( $data ); 
  189.  
  190. // Verify response is a JSON encoded object. 
  191. if( ! is_object( $response ) ) { 
  192. // Could not decode response. 
  193. return false; 
  194.  
  195. return $response; 
  196.  
  197. private function ChainPay_ValidateSignature($message, $signature, $key) 
  198. $hmac = hash_hmac('sha256', $message, $key ); 
  199. $hmacBytes = pack('H*', $hmac);  
  200.  
  201. if($hmacBytes != $signature) 
  202. $this->log->add('ChainPay', 'Invalid message signature: ' . $message); 
  203. return false; 
  204. return true; 
  205.  
  206. public function ChainPay_Callback() 
  207. @ob_clean(); 
  208. global $wpdb; 
  209.  
  210. $data = file_get_contents('php://input'); 
  211.  
  212. $callbackId = $_SERVER['HTTP_X_ALTXE_CALLBACKID']; 
  213. $callbackType = $_SERVER['HTTP_X_ALTXE_CALLBACKTYPE']; 
  214. $callbackCreated = $_SERVER['HTTP_X_ALTXE_CALLBACKCREATED']; 
  215. $callbackAttempt = $_SERVER['HTTP_X_ALTXE_CALLBACKATTEMPT']; 
  216. $callbackSignature = $_SERVER['HTTP_X_ALTXE_SIGNATURE']; 
  217. $callbackSalt = $_SERVER['HTTP_X_ALTXE_SALT']; 
  218.  
  219. $signature = base64_decode($callbackSignature); 
  220. $salt = base64_decode($callbackSalt); 
  221. $key = base64_decode($this->privateKey) . $salt; 
  222.  
  223. $isValid = $this->ChainPay_ValidateSignature($data, $signature, $key); 
  224. if($isValid != false) 
  225. $event = $this->ChainPay_DecodeResponse($data); 
  226. if($this->debug) 
  227. $this->log->add('ChainPay', 'WebHook object received: ' . json_encode($event)); 
  228.  
  229. if($event != false) 
  230. $invoiceId = $event->InvoiceId; 
  231. $reference = $event->Reference; 
  232.  
  233. // Find our OrderId based on Reference. 
  234. $metadata = $wpdb->get_row("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'chainpay_invoice_id' AND meta_value = '$invoiceId'"); 
  235. $orderId = $metadata->post_id; 
  236. $order = new WC_Order($orderId); 
  237. if($order->id == $reference) 
  238. switch($callbackType) 
  239. case 'InvoicePaid': 
  240. if($this->debug) 
  241. $this->log->add('ChainPay', 'WebHook - OrderId: ' . $orderId . ' is now Paid.'); 
  242.  
  243. // Order is Paid but not yet confirmed, put it On-Hold (Awaiting Payment). 
  244. $order->update_status('on-hold', __('Bitcoin payment received, awaiting confirmation.', 'wcchainpay')); 
  245.  
  246. // Reduce stock levels 
  247. $order->reduce_order_stock(); 
  248.  
  249. break; 
  250. case 'InvoiceCompleted': 
  251.  
  252. if($this->debug) 
  253. $this->log->add('ChainPay', 'WebHook - OrderId: ' . $orderId . ' is now Completed.'); 
  254. // Order is now confirmed and can be completed. 
  255.  
  256. $order->add_order_note(__('Bitcoin payment confirmed.', 'wcchainpay')); 
  257. $order->payment_complete(); 
  258.  
  259. break; 
  260. case 'InvoiceExpired': 
  261.  
  262. if($this->debug) 
  263. $this->log->add('ChainPay', 'WebHook - OrderId: ' . $orderId . ' is now Expired (Cancelled).'); 
  264.  
  265. $order->cancel_order('Bitcoin payment expired.'); 
  266.  
  267. break; 
  268.  
  269. case 'InvoiceUnderpaid': 
  270.  
  271. if($this->debug) 
  272. $this->log->add('ChainPay', 'WebHook - OrderId: ' . $orderId . ' is now Underpaid.'); 
  273.  
  274. $order->update_status('on-hold', __('Bitcoin payment received, not enough funds sent. Expected: ' . $event->CryptoAmountExpected . ' BTC Received: ' . $event->CryptoAmountReceived . ' BTC Outstanding: ' . $event->CryptoAmountOutstanding . ' BTC. Request they send the outstanding BTC to: ' . $event->CryptoAddress, 'wcchainpay')); 
  275. return true; 
  276. else 
  277. if($this->debug) 
  278. $this->log->add('ChainPay', 'Could not locate Order relating to WebHook event: ' . json_encode($data)); 
  279.  
  280. $this->log->add('ChainPay', 'WebHook event failure: ' . json_encode($data)); 
  281.  
  282. wp_die( __( 'ChainPay Webhook Failure', 'wc-chainpay' ) ); 
  283.  
  284. public function ChainPay_MissingApiKey() { 
  285. $html = '<div class="error">'; 
  286. $html .= '<p>' . sprintf( __( '<strong>ChainPay Disabled</strong> Please enter your API Key from the <a href="https://portal.chainpay.com">ChainPay Portal</a>. %sClick here to configure!%s', 'wcchainpay' ), '<a href="' . get_admin_url() . 'admin.php?page=wc-settings&tab=checkout&section=wc_chainpay">', '</a>' ) . '</p>'; 
  287. $html .= '</div>'; 
  288.  
  289. echo $html; 
  290.  
  291. public function ChainPay_MissingPrivateKey() { 
  292. $html = '<div class="error">'; 
  293. $html .= '<p>' . sprintf( __( '<strong>ChainPay Disabled</strong> Please enter your Private Key from the <a href="https://portal.chainpay.com">ChainPay Portal</a>. %sClick here to configure!%s', 'wcchainpay' ), '<a href="' . get_admin_url() . 'admin.php?page=wc-settings&tab=checkout&section=wc_chainpay">', '</a>' ) . '</p>'; 
  294. $html .= '</div>'; 
  295.  
  296. echo $html;