Guest User

Untitled

a guest
Apr 8th, 2024
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.79 KB | None | 0 0
  1. <?php
  2. /*
  3. Plugin Name: Binance Pay Woocommerce
  4. Plugin URI:
  5. Description: A payment gateway that allows your customers to pay with cryptocurrency via Binance
  6. Version: 1.1.7
  7. Author: Binance
  8. Author URI:
  9. License: GPLv3+
  10. License URI: https://www.gnu.org/licenses/gpl-3.0.html
  11. Text Domain: binance
  12. Domain Path: /languages
  13. */
  14. if (!defined('ABSPATH')) {
  15. exit;
  16. }
  17.  
  18. add_filter('woocommerce_payment_gateways', 'binance_pay_add_gateway_class');
  19. function binance_pay_add_gateway_class($gateways)
  20. {
  21. $gateways[] = 'Binance_Pay_Gateway';
  22. return $gateways;
  23. }
  24.  
  25. add_action('plugins_loaded', 'binance_pay_init_gateway_class');
  26.  
  27.  
  28. function binance_pay_init_gateway_class()
  29. {
  30.  
  31. class Binance_Pay_Gateway extends WC_Payment_Gateway
  32. {
  33.  
  34. // Explicitly declare the properties
  35. public $api_path;
  36. public $api_key;
  37. public $secret_key;
  38. public $transaction_currency;
  39.  
  40. public function __construct()
  41. {
  42. $this->id = 'binance';
  43. $this->has_fields = false;
  44. $this->method_title = 'Binance Pay';
  45. $this->icon = apply_filters('woocommerce_binance_pay_icon', plugins_url('/assets/binance-logo.svg', __FILE__));
  46. $this->method_description = 'A payment gateway that sends your customers to Binance to pay with cryptocurrency.';
  47.  
  48. $this->init_form_fields();
  49. $this->init_settings();
  50. $this->title = $this->get_option('title');
  51. $this->enabled = $this->get_option('enabled');
  52.  
  53. // Set the values for these properties
  54. $this->api_path = "https://bpay.binanceapi.com/binancepay/openapi/";
  55. $this->api_key = $this->get_option('api_key');
  56. $this->secret_key = $this->get_option('secret_key');
  57. $this->transaction_currency = $this->get_option('transaction_currency');
  58.  
  59. add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
  60. add_action('woocommerce_api_wc_gateway_binance', array($this, 'binance_pay_handle_webhook'));
  61. }
  62.  
  63.  
  64. public function init_form_fields()
  65. {
  66. $this->form_fields = array(
  67. 'enabled' => array(
  68. 'title' => 'Enable/Disable',
  69. 'label' => 'Enable Binance Pay Gateway',
  70. 'type' => 'checkbox',
  71. 'description' => '',
  72. 'default' => 'no'
  73. ),
  74. 'api_key' => array(
  75. 'title' => 'API Key',
  76. 'type' => 'text'
  77. ),
  78. 'secret_key' => array(
  79. 'title' => 'Secret Key',
  80. 'type' => 'password',
  81. ),
  82. 'transaction_currency' => array(
  83. 'title' => 'Currency',
  84. 'type' => 'select',
  85. 'class' => 'wc-enhanced-select',
  86. 'description' => 'This is the currency used to create order in Binance Pay. With fiat selection, your customers will pay you with equivalent USDT, and your settlement currency will be in USDT as well.', 'woocommerce',
  87. 'default' => '',
  88. 'desc_tip' => true,
  89. 'custom_attributes' => array('required' => 'required'),
  90. 'options' => array(
  91. 'USDT' => 'USDT',
  92. 'USD' => 'USD',
  93. 'EUR' => 'EUR',
  94. 'CHF' => 'CHF',
  95. 'GBP' => 'GBP',
  96. 'ARS' => 'ARS',
  97. 'CNY' => 'CNY',
  98. 'HKD' => 'HKD',
  99. 'NGN' => 'NGN',
  100. ),
  101. )
  102. );
  103. }
  104.  
  105. public function payment_scripts()
  106. {
  107. }
  108.  
  109. public function validate_fields()
  110. {
  111.  
  112. }
  113.  
  114. /**
  115. * Get payment method title
  116. *
  117. * @return string
  118. */
  119. public function get_title()
  120. {
  121. return $this->method_title;
  122. }
  123.  
  124.  
  125. public function process_payment($order_id)
  126. {
  127. global $woocommerce;
  128. $order = new WC_Order($order_id);
  129. $result = $this->create_binance_order($order_id);
  130.  
  131. // Check if 'code' is set and equals '000000', indicating success
  132. if (!isset($result['code']) || $result['code'] != '000000') {
  133. $errorMessage = isset($result['errorMessage']) ? $result['errorMessage'] : 'An unspecified error occurred.';
  134. wc_add_notice('Payment error: ' . $errorMessage, 'error');
  135. return array('result' => 'fail');
  136. }
  137.  
  138. // Check if 'data' is set and contains the required information
  139. if (!isset($result['data'], $result['data']['prepayId'], $result['data']['universalUrl'])) {
  140. wc_add_notice('Payment error: The response from the payment gateway is incomplete.', 'error');
  141. return array('result' => 'fail');
  142. }
  143.  
  144. $detail = $result['data'];
  145. $order->update_status('on-hold', 'Awaiting Binance payment');
  146. $order->update_meta_data('binance_pay_prepay_id', $detail['prepayId']);
  147. $order->save();
  148.  
  149. $woocommerce->cart->empty_cart();
  150. return array(
  151. 'result' => 'success',
  152. 'redirect' => $detail['universalUrl'],
  153. );
  154. }
  155.  
  156.  
  157.  
  158. public function generate_random_string()
  159. {
  160. $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  161. $charactersLength = strlen($characters);
  162. $randomString = '';
  163. for ($i = 0; $i < 32; $i++) {
  164. $randomString .= $characters[rand(0, $charactersLength - 1)];
  165. }
  166. return $randomString;
  167. }
  168.  
  169. public function create_binance_order($order_id)
  170. {
  171. $order = new WC_Order($order_id);
  172. $req = array(
  173. 'env' => array('terminalType' => 'WEB'),
  174. 'merchantTradeNo' => $order_id
  175. );
  176. $currency = $this->transaction_currency;
  177. if (empty($currency) || $currency == 'BUSD') {
  178. $currency = 'USDT';
  179. }
  180. if ($currency == 'USDT') {
  181. $req['orderAmount'] = $order->get_total();
  182. $req['currency'] = $currency;
  183. } else {
  184. $req['fiatAmount'] = $order->get_total();
  185. $req['fiatCurrency'] = $currency;
  186. }
  187. $req['goods'] = array();
  188. $req['passThroughInfo'] = "wooCommerce-1.0";
  189. $req['goods']['goodsType'] = "02";
  190. $req['goods']['goodsCategory'] = "Z000";
  191. $referenceGoodsId = '';
  192. $goodsName = '';
  193. $index = 0;
  194. foreach ($order->get_items() as $item_id => $item) {
  195. $product_id = (string)$item->get_product_id();
  196. if ($index == 0) {
  197. $referenceGoodsId = $product_id;
  198. $goodsName = $item->get_name();
  199. } else {
  200. $referenceGoodsId .= ', ' . $product_id;
  201. $goodsName .= ', ' . $item->get_name();
  202. }
  203. $index++;
  204. }
  205. $req['goods']['referenceGoodsId'] = $referenceGoodsId;
  206. $req['goods']['goodsName'] = $goodsName;
  207. $req['returnUrl'] = $this->get_return_url($order);
  208. $req['cancelUrl'] = $order->get_cancel_order_url();
  209. $req['webhookUrl'] = esc_url(home_url('/')) . '?wc-api=wc_gateway_binance';
  210. $nonce = $this->generate_random_string();
  211. $body = json_encode($req);
  212. $microtime = microtime(true);
  213. $seconds = floor($microtime);
  214. $milliseconds = sprintf('%03d', ($microtime - $seconds) * 1000);
  215. $timestamp = $seconds . $milliseconds;
  216. $payload = $timestamp . "\n" . $nonce . "\n" . $body . "\n";
  217. $secretKey = $this->secret_key;
  218. $signature = strtoupper(hash_hmac('sha512', $payload, $secretKey));
  219. $apiKey = $this->api_key;
  220.  
  221. $headers = array(
  222. 'Content-Type' => 'application/json',
  223. "BinancePay-Timestamp" => $timestamp,
  224. "BinancePay-Nonce" => $nonce,
  225. "BinancePay-Certificate-SN" => $apiKey,
  226. "BinancePay-Signature" => $signature
  227. );
  228. $args = array(
  229. 'body' => json_encode($req),
  230. 'timeout' => '60',
  231. 'redirection' => '8',
  232. 'httpversion' => '1.0',
  233. 'blocking' => true,
  234. 'headers' => $headers,
  235. 'cookies' => array(),
  236. );
  237. $response = wp_remote_post($this->api_path . 'v2/order', $args);
  238. $responseBody = wp_remote_retrieve_body($response);
  239. error_log("binance response " . $responseBody);
  240. return json_decode($responseBody, true);
  241. }
  242.  
  243. public function binance_pay_handle_webhook()
  244. {
  245. $body = file_get_contents('php://input');
  246. $timestamp = sanitize_text_field($_SERVER['HTTP_BINANCEPAY_TIMESTAMP']);
  247. $nonce = sanitize_text_field($_SERVER['HTTP_BINANCEPAY_NONCE']);
  248. $payload = $timestamp . "\n" . $nonce . "\n" . $body . "\n";
  249. $signature = sanitize_text_field($_SERVER['HTTP_BINANCEPAY_SIGNATURE']);
  250. if (!empty($body) && $this->validate_webhook($payload, $signature)) {
  251. $this->process_callback(json_decode($body, true));
  252. echo '{"returnCode":"SUCCESS"}';
  253. exit;
  254. } else {
  255. wp_die('Binance Webhook Request Failure', 'Binance Webhook', array('response' => 500));
  256. }
  257. }
  258.  
  259. public function validate_webhook($payload, $signature)
  260. {
  261. $decodedSignature = base64_decode($signature);
  262. $pubKey = "-----BEGIN PUBLIC KEY-----
  263. MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwuF7PgDsNBuJVZ6HeVoH
  264. T2Tqj22+eWLQ/kZbYj3CTgdvedFymj0Kqvxtwy3InVbU6t6g5UkjL+dMOAkt5GxL
  265. NYI1uNy9g3+mifCDRXDArwvcKkB5jYu0R3WTNtf1ODicjpOf1NUqMZ+0t3jNwVAy
  266. awvxlyxpX8gMa6OAMbzMtH3iskM52nu5mS57Xh4ryibwjIxd0ssb63gD2qH8jy60
  267. AK/qgkijlysgEQDzYTk6X2x4t9BfVoOL3+yxkIiwnfL/KY9xkvSmWuAFIZqu4pY7
  268. g+GXFiG50sSCe2BkBcSzIS56L1Qp/tSzDUl1+fQCGhA3BFY42/zTpvdjLLUgbRYZ
  269. pJCu9Z4w0HsM118rKCxBZNveoc12oHXEbDMDy7y/c39KYNyniCH6iKPNzu6Zi8tb
  270. XXN7KG9mUHUzstnafVd5QpqIumQUgE+JVTSrdx0YJy7OQeqeSoQeBeI7pr1gsRuH
  271. x0pcniYOIRwmtZ27Ybkbk0zOu1vBmzE8hC8RAkE8Yz06T7quoa547FicUYQBvtkR
  272. YLJDbSIjFLkfTFNOgV5VU92JfJvFji3F/nDVQ0gI6iuDktKYB0FNe1LZvKbDgPs+
  273. J8/Pssd1DOW8XJbQXmJz8VCrubv/SdOYsy0lP0m/ZybEFjSVSWKT3xCpHVSDVJNm
  274. rTUypediX9eeNMlfs0x/vmkCAwEAAQ==
  275. -----END PUBLIC KEY-----";
  276. $result = openssl_verify($payload, $decodedSignature, $pubKey, OPENSSL_ALGO_SHA256);
  277. if ($result === 1) {
  278. return true;
  279. }
  280. return false;
  281. }
  282.  
  283. public function process_callback($body)
  284. {
  285. if ($body["bizType"] == "PAY") {
  286. $data = json_decode($body["data"], true);
  287. $order_id = $data["merchantTradeNo"];
  288. $order = wc_get_order($order_id);
  289. if ($body["bizStatus"] == "PAY_SUCCESS") {
  290. $order->update_status('processing', __('binance payment success', 'binance'));
  291. $order->payment_complete();
  292. }
  293. if ($body["bizStatus"] == "PAY_CLOSED") {
  294. $order->update_status('cancelled', __('binance payment expired.', 'binance'));
  295. }
  296. }
  297. }
  298. }
  299. }
  300.  
  301.  
  302.  
Add Comment
Please, Sign In to add comment