'POST', 'permission_callback' => '__return_true', 'callback' => 'ibrese_handle_pos_webhook', ]); }); function ibrese_handle_pos_webhook(WP_REST_Request $request) { $raw = $request->get_body(); $secret = get_option('ibrese_webhook_secret'); $header = $request->get_header('x-ibrese-webhook-signature'); if (!$secret || !ibrese_verify_hmac($secret, $header, $raw)) { return new WP_REST_Response(['error' => 'bad signature'], 401); } $event = json_decode($raw, true); if (($event['type'] ?? '') !== 'payment.finalized' || empty($event['invoicePaid'])) { return new WP_REST_Response(['ok' => true, 'ignored' => true], 200); } $ref = sanitize_text_field($event['merchantReference'] ?? ''); $payment_id = preg_replace('/[^0-9a-f]/', '', strtolower($event['paymentId'] ?? '')); if ($ref === '' || strlen($payment_id) !== 64) { return new WP_REST_Response(['error' => 'bad event'], 400); } $obs = wp_remote_get('https://rpc.ibrese.com/payments/' . $payment_id, ['timeout' => 8]); if (is_wp_error($obs)) { return new WP_REST_Response(['error' => 'node unreachable'], 502); } $body = json_decode(wp_remote_retrieve_body($obs), true); $paid = ($body['status'] ?? '') === 'FINALIZED' && in_array($body['amountRelation'] ?? '', ['MATCH', 'OVERPAYMENT'], true); if (!$paid) { return new WP_REST_Response(['ok' => true, 'settled' => false], 200); } $order = wc_get_order(absint(str_replace('ORDER-', '', $ref))); if ($order && !$order->is_paid()) { $order->payment_complete($payment_id); $order->add_order_note('IBRESE FINALIZED ' . $payment_id); } return new WP_REST_Response(['ok' => true], 200); } function ibrese_verify_hmac($secret, $header, $raw) { $map = []; foreach (explode(',', (string) $header) as $part) { $i = strpos($part, '='); if ($i > 0) { $map[trim(substr($part, 0, $i))] = trim(substr($part, $i + 1)); } } $t = intval($map['t'] ?? 0); $v1 = $map['v1'] ?? ''; if ($t <= 0 || !preg_match('/^[0-9a-f]{64}$/', $v1)) { return false; } if (abs((int) round(microtime(true) * 1000) - $t) > 300000) { return false; } return hash_equals(hash_hmac('sha256', $t . '.' . $raw, $secret), $v1); } /** * Checkout'ta fatura açmak için (admin-ajax veya REST): * * $amount_subunits = (string) (intval(round($order->get_total() * 100)) * 1000); * wp_remote_post($pos . '/v1/pos/invoices', [ * 'headers' => [ * 'Authorization' => 'Bearer ' . get_option('ibrese_pos_api_key'), * 'Content-Type' => 'application/json', * ], * 'body' => wp_json_encode([ * 'amount' => $amount_subunits, * 'merchantReference' => 'ORDER-' . $order->get_id(), * ]), * ]); */