** * Plugin Name: WC Fiken Invoice Import * Description: Eksporter WooCommerce-ordrer til Fiken – automatisk, manuell og test. * Version: 1.0.19 * Author: Ditt navn */ if ( ! defined( 'ABSPATH' ) ) { exit; } define( 'FIKEN_API_BASE', 'https://api.fiken.no/api/v2' ); define( 'FIKEN_COMPANY_SLUG', 'oa-rindalsholt-merchandise' ); define( 'FIKEN_ACCESS_TOKEN', '9136752251.QwVH4disGBBHeJj8ERUZHZI7y08MgNgB' ); function fiken_log( $level, $message, $context = [] ) { if ( ! function_exists( 'wc_get_logger' ) ) return; wc_get_logger()->log( $level, $message . ' | ' . wp_json_encode( $context ), [ 'source' => 'fiken' ] ); } class WC_Fiken_Full_Integration { protected $last_error = ''; public function __construct() { add_action( 'woocommerce_order_status_completed', [ $this, 'on_order_completed' ] ); add_action( 'admin_menu', [ $this, 'add_tools_pages' ] ); } public function on_order_completed( $order_id ) { $this->send_order_to_fiken( $order_id ); } public function add_tools_pages() { add_management_page( 'Fiken Import', 'Fiken Import', 'manage_woocommerce', 'fiken-import', [ $this, 'render_import_page' ] ); add_management_page( 'Fiken Test', 'Fiken Test', 'manage_woocommerce', 'fiken-test', [ $this, 'render_test_page' ] ); } public function render_import_page() { echo '

Importer fullførte ordre til Fiken

'; echo '
'; wp_nonce_field( 'fiken_import_nonce', 'fiken_import_nonce' ); echo '

Fra dato:

'; echo '

'; echo '
'; if ( ! empty( $_POST['fiken_import_date'] ) && check_admin_referer( 'fiken_import_nonce', 'fiken_import_nonce' ) ) { $date = sanitize_text_field( $_POST['fiken_import_date'] ) . ' 00:00:00'; $this->import_since( $date ); } echo '
'; } protected function import_since( $datetime ) { $orders = wc_get_orders( [ 'limit' => -1, 'status' => 'completed', 'date_completed' => '>' . $datetime, ] ); echo '

Fant ' . count( $orders ) . ' ordre

« Tilbake

'; } public function render_test_page() { echo '

Fiken Test

'; $result = ''; if ( isset( $_POST['fiken_test_order'] ) && check_admin_referer( 'fiken_test_nonce', 'fiken_test_nonce' ) ) { $key = sanitize_text_field( $_POST['fiken_test_order'] ); $order = wc_get_order( intval( $key ) ); if ( ! $order ) { foreach ( wc_get_orders( [ 'limit' => -1 ] ) as $o ) { if ( (string) $o->get_order_number() === $key ) { $order = $o; break; } } } if ( $order ) { $ok = $this->send_order_to_fiken( $order->get_id() ); $result = $ok ? '

✅ Order sendt til Fiken!

' : '

❌ Kunne ikke sende order: ' . esc_html( $this->last_error ) . '

'; } else { $result = '

❌ Fant ikke ordre “'. esc_html( $key ) .'”.

'; } } echo $result; echo '
'; wp_nonce_field( 'fiken_test_nonce', 'fiken_test_nonce' ); echo '


'; echo '

'; echo '

'; echo '
'; } protected function invoice_exists( $our_reference ) { $url = FIKEN_API_BASE . "/companies/" . FIKEN_COMPANY_SLUG . "/invoices?search=" . rawurlencode( $our_reference ); $resp = wp_remote_get( $url, [ 'headers' => [ 'Authorization' => 'Bearer ' . FIKEN_ACCESS_TOKEN ], 'timeout' => 15, ] ); if ( wp_remote_retrieve_response_code( $resp ) !== 200 ) { return false; } $list = json_decode( wp_remote_retrieve_body( $resp ), true ); foreach ( $list as $inv ) { if ( ! empty( $inv['ourReference'] ) && (string) $inv['ourReference'] === (string) $our_reference ) { return true; } } return false; } public function send_order_to_fiken( $order_id ) { $this->last_error = ''; $order = wc_get_order( $order_id ); if ( ! $order ) { $this->last_error = "Order $order_id ikke funnet"; return false; } // 1) Sikre kontakt $contact_id = $this->ensure_contact( $order ); if ( ! $contact_id ) { return false; // $last_error satt } // 2) Opprett faktura if ( ! $this->send_invoice_to_fiken( $order, $contact_id ) ) { return false; } return true; } protected function ensure_contact( $order ) { $b = $order->get_address( 'billing' ); $street_full = trim( $b['address_1'] . ( $b['address_2'] ? ' ' . $b['address_2'] : '' ) ); $payload = [ 'name' => trim( $b['first_name'] . ' ' . $b['last_name'] ), 'email' => $b['email'], 'phone' => $b['phone'], 'customer' => true, 'address' => [ 'street' => $street_full, 'street2' => $b['address_2'] ?: '', 'postalCode' => $b['postcode'], 'city' => $b['city'], 'country' => $b['country'], ], ]; // Sjekk om eksisterende $url = FIKEN_API_BASE . "/companies/" . FIKEN_COMPANY_SLUG . "/contacts?customer=true&search=" . rawurlencode( $payload['email'] ); $resp = wp_remote_get( $url, [ 'headers' => [ 'Authorization' => 'Bearer ' . FIKEN_ACCESS_TOKEN ], 'timeout' => 15 ] ); if ( wp_remote_retrieve_response_code( $resp ) === 200 ) { $list = json_decode( wp_remote_retrieve_body( $resp ), true ); foreach ( $list as $c ) { if ( $c['email'] === $payload['email'] && $c['phone'] === $payload['phone'] && $c['address']['street'] === $payload['address']['street'] && $c['address']['postalCode'] === $payload['address']['postalCode'] ) { return $c['contactId']; } } } // Opprett ny $post_url = FIKEN_API_BASE . "/companies/" . FIKEN_COMPANY_SLUG . "/contacts"; $resp2 = wp_remote_post( $post_url, [ 'headers' => [ 'Authorization' => 'Bearer ' . FIKEN_ACCESS_TOKEN, 'Content-Type' => 'application/json', ], 'body' => wp_json_encode( $payload ), 'timeout' => 20, ] ); $code2 = wp_remote_retrieve_response_code( $resp2 ); $body2 = wp_remote_retrieve_body( $resp2 ); if ( in_array( $code2, [200,201], true ) ) { $new = json_decode( $body2, true ); if ( empty( $new['contactId'] ) ) { $loc = wp_remote_retrieve_header( $resp2, 'location' ); if ( preg_match( '@/contacts/(\d+)@', $loc, $m ) ) { $new['contactId'] = $m[1]; } } if ( ! empty( $new['contactId'] ) ) { return $new['contactId']; } } $this->last_error = "Opprett kunde feilet: HTTP {$code2} – {$body2}"; return false; } protected function send_invoice_to_fiken( $order, $contact_id ) { $date = $order->get_date_created()->date_i18n( 'Y-m-d' ); $payload = [ 'customerId' => $contact_id, 'documentDate' => $date, 'issueDate' => $date, 'dueDate' => $date, 'ourReference' => $order->get_order_number(), 'cash' => false, 'bankAccountCode' => '1960:10003', 'lines' => $this->build_invoice_payload( $order ), ]; $resp = wp_remote_post( FIKEN_API_BASE . '/companies/' . FIKEN_COMPANY_SLUG . '/invoices', [ 'headers' => [ 'Authorization' => 'Bearer ' . FIKEN_ACCESS_TOKEN, 'Content-Type' => 'application/json', ], 'body' => wp_json_encode( $payload ), 'timeout' => 20, ] ); $code = wp_remote_retrieve_response_code( $resp ); $body = wp_remote_retrieve_body( $resp ); if ( $code !== 201 ) { $this->last_error = "Opprett faktura feilet: HTTP {$code} – {$body}"; return false; } return true; } protected function build_invoice_payload( $order ) { $lines = []; // Produkter foreach ( $order->get_items() as $item ) { $qty = (float) $item->get_quantity(); $total = (float) $item->get_total(); $unit = round( ( $total / max(1, $qty ) ) * 100, 0 ); $vat_pct = stripos( $item->get_product()->get_sku(), 'KAMUI' ) !== false ? 0 : 25; $acc = $vat_pct === 0 ? '3100' : '3000'; $lines[] = [ 'description' => $item->get_name(), 'quantity' => $qty, 'unitPrice' => $unit, 'vatInPercent' => $vat_pct, 'incomeAccount'=> $acc, 'articleNumber'=> $item->get_product()->get_sku(), ]; } // Frakt foreach ( $order->get_items( 'shipping' ) as $ship ) { $ship_total = (float) $ship->get_total(); if ( $ship_total > 0 ) { $lines[] = [ 'description' => 'Frakt: ' . $ship->get_method_title(), 'quantity' => 1, 'unitPrice' => round( $ship_total * 100, 0 ), 'vatInPercent' => 25, 'incomeAccount'=> '3006', 'articleNumber'=> 'FRAKT', ]; } } return $lines; } } new WC_Fiken_Full_Integration(); Harry Potter - Hogwarts Crest T-Shirt - Nerdeportalen - Cosplay og populærkultur for alle!

Harry Potter – Hogwarts Crest T-Shirt

Harry Potter – Hogwarts Crest T-Shirt

Fra 259,-

Produktnummer: 1-HP-3-HPHC-BLACK Kategorier: , , , , ,

Fra 259,-

Produktnummer: 1-HP-3-HPHC-BLACK Kategorier: , , , , ,
Se 0 resultater