PluginProbe
Pay with Vipps and MobilePay for WooCommerce / 6.2.5
Pay with Vipps and MobilePay for WooCommerce v6.2.5
6.2.5 6.2.4 6.2.3 6.2.2 6.2.1 6.2.0 6.1.10 6.1.9 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1.0 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 5.4.3 5.4.2 All 187 releases
← All changes | payment/VippsApi.class.php +31 -146 5.4.2 → 6.2.5 View file →
@@ -506,8 +506,11 @@
506 506 $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
507 507 }
508 508
509 509 if (!$idempotency_key) $idempotency_key = $order->get_order_key();
510 +
511 + // We now support two gateways: 'vipps' and 'vipps_card' for credit card payments.
512 + $gateway = $order->get_payment_method();
510 513
511 514 // Make sure to clean up old metas, since we now support restarting order payment with Vipps retry sesssions,
512 515 // so these may be set and cause conflicts. LP 2026-03-11
513 516 if ($order->get_meta('_vipps_shipping_set')) {
@@ -527,8 +530,12 @@
527 530 // Make it easier to find express checkout orders in Vipps' backend IOK 2025-10-29
528 531 if ($express) {
529 532 $headers['Vipps-System-Plugin-Name'] = 'woo-vipps-express';
530 533 }
534 + // And credit card payments the same IOK 2026-05-27
535 + if ($gateway == 'vipps_card') {
536 + $headers['Vipps-System-Plugin-Name'] = 'woo-vipps-card';
537 + }
531 538
532 539 // We will use this to retrieve the orders in the callback, since the prefix can change in the admin interface. IOK 2018-05-03
533 540 // This is really for the new epayment api only, but we do this to ensure we use the same logic. For short prefixes and order numbers.
534 541 // Pad orderid with 0 to the left so the entire vipps-orderid/reference is at least 8 chars long. IOK 2022-04-06
@@ -565,9 +572,21 @@
565 572
566 573
567 574 $data = [];
568 575 $data['reference'] = $vippsorderid;
576 +
577 + // WEB_REDIRECT is the normal flow; requires a returnUrl. PUSH_MESSAGE requires a valid customer (phone number)
578 + // NATIVE_REDIRECT is for automatic app switch between a native app and the Vipps MobilePay app.
579 + // QR returns a QR code that can be scanned to complete the payment. IOK 2023-12-13
580 + $data['userFlow'] = apply_filters('woo_vipps_payment_user_flow', 'WEB_REDIRECT', $orderid);
581 +
569 582 $data['paymentMethod'] = ['type' => 'WALLET']; // This is the Vipps MobilePay app. CARD is credit card, must then use userFlow WEB_REDIRECT
583 +
584 + if ($gateway == 'vipps_card') {
585 + $data['paymentMethod'] = ['type' => 'CARD'];
586 + $data['userFlow'] = 'WEB_REDIRECT';
587 + }
588 +
570 589 $data['amount'] = ['currency' => $order->get_currency(), 'value' => round(wc_format_decimal($order->get_total(),'') * 100)];
571 590 $data['returnUrl'] = $fallback;
572 591
573 592 $data['customer'] = [];
@@ -628,12 +647,8 @@
628 647 $minage = null;
629 648 }
630 649 $data['minimumUserAge'] = $minage;
631 650
632 - // WEB_REDIRECT is the normal flow; requires a returnUrl. PUSH_MESSAGE requires a valid customer (phone number)
633 - // NATIVE_REDIRECT is for automatic app switch between a native app and the Vipps MobilePay app.
634 - // QR returns a QR code that can be scanned to complete the payment. IOK 2023-12-13
635 - $data['userFlow'] = apply_filters('woo_vipps_payment_user_flow', 'WEB_REDIRECT', $orderid);
636 651
637 652 // Some control over the QR
638 653 if ($data['userFlow'] == 'QR') {
639 654 // Formats are IMAGE/SVG+XML, TEXT/TARGETURL, IMAGE/PNG
@@ -723,9 +738,9 @@
723 738 return $res;
724 739 }
725 740
726 741
727 - // This is Vipps Checkout IOK 2021-06-19
742 + // This is Checkout IOK 2021-06-19
728 743 // Updated for V3 2023-01-09
729 744 public function initiate_checkout($customerinfo,$order,$returnurl,$authtoken,$idempotency_key=null) {
730 745 $command = 'checkout/v3/session';
731 746 $static_shipping = $order->get_meta('_vipps_static_shipping');
@@ -799,9 +814,9 @@
799 814 $transaction['paymentDescription'] = substr($transaction['paymentDescription'],0,90); // Add some slack if this happens. IOK 2019-10-17
800 815 }
801 816
802 817
803 - ## Vipps Checkout Shipping
818 + ## Checkout Shipping
804 819 $shippingcallback = $this->gateway->shipping_details_callback_url($authtoken, $orderid);
805 820 $shippingcallback .= "/v3/checkout/" . $vippsorderid . "/shippingDetails"; # because this is how eCom v2 does it.
806 821 $gw = $this->gateway;
807 822 if ($needs_shipping) {
@@ -873,9 +888,9 @@
873 888 $configuration['elements'] = "Full";
874 889 $configuration['customerInteraction'] = apply_filters('woo_vipps_checkout_customerInteraction', 'CUSTOMER_NOT_PRESENT', $orderid);
875 890 $configuration['userFlow'] = "WEB_REDIRECT"; // Change to NATIVE_REDIRECT for apps in below filter
876 891 // Require consent of email and openid sub - really for login
877 - $configuration['requireUserInfo'] = apply_filters('woo_vipps_checkout_requireUserInfo', $gw->get_option('requireUserInfo_checkout') == 'yes' , $orderid);
892 + $configuration['requireUserInfo'] = (bool) apply_filters('woo_vipps_checkout_requireUserInfo', $gw->get_option('requireUserInfo_checkout') == 'yes' , $orderid);
878 893
879 894
880 895 // IOK 2023-12-22 and we can add an order summary, so do so by default
881 896 $summarize = apply_filters('woo_vipps_checkout_show_order_summary', true, $order);
@@ -912,11 +927,12 @@
912 927 // Should return a map from other_method => ['gw'=>'gateway key or any or empty string]
913 928 $other_payment_methods = apply_filters('woo_vipps_checkout_external_payment_methods', VippsCheckout::instance()->external_payment_methods(), $order);
914 929 if (!empty($other_payment_methods)) {
915 930 $others = [];
931 + $cb = wp_create_nonce('vipps_gw_' . $orderid);
916 932 foreach ($other_payment_methods as $methodkey => $methoddata) {
917 933 $chooseanother = ['action'=>'vipps_gw', 'o'=>$orderid];
918 - $chooseanother['cb'] = wp_create_nonce('vipps_gw');
934 + $chooseanother['cb'] = $cb;
919 935 $chooseanother['gw'] = ($methoddata['gw'] ?? "");
920 936 $others[] = ['paymentMethod' => $methodkey, 'redirectUrl'=> add_query_arg($chooseanother,admin_url("admin-post.php")) ];
921 937 }
922 938 if (!empty($others)) {
@@ -934,10 +950,10 @@
934 950 $configuration['customConsent'] = $customconsent;
935 951 }
936 952
937 953 if (!$needs_shipping) {
938 - $nocontacts = $this->gateway->get_option('noContactFields') == 'yes';
939 - $noaddress = $this->gateway->get_option('noAddressFields') == 'yes';
954 + $nocontacts = (bool) ($this->gateway->get_option('noContactFields') == 'yes');
955 + $noaddress = (bool) ($this->gateway->get_option('noAddressFields') == 'yes');
940 956 if ($noaddress) {
941 957 $configuration['elements'] = "PaymentAndContactInfo";
942 958 }
943 959 // AddressFields cannot be enabled while ContactFields is disabled
@@ -1059,143 +1075,9 @@
1059 1075 }
1060 1076 return $res;
1061 1077 }
1062 1078
1063 - // Capture a payment made. Amount is in cents and required. IOK 2018-05-07
1064 - public function capture_payment($order,$amount,$requestid=1) {
1065 - $orderid = $order->get_meta('_vipps_orderid');
1066 1079
1067 - $command = 'Ecomm/v2/payments/'.$orderid.'/capture';
1068 - $msn = $this->get_merchant_serial();
1069 - $subkey = $this->get_key($msn);
1070 - if (!$subkey) {
1071 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1072 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1073 - }
1074 - if (!$msn) {
1075 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1076 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1077 - }
1078 - $headers = $this->get_headers($msn);
1079 - $headers['X-Request-Id'] = $requestid;
1080 -
1081 - $transaction = array();
1082 - // Ignore refOrderId - for child-transactions
1083 - $transaction['amount'] = round($amount);
1084 -
1085 - $shop_identification = apply_filters('woo_vipps_transaction_text_shop_id', home_url());
1086 -
1087 - $transaction['transactionText'] = __('Order capture for order','woo-vipps') . ' ' . $orderid . ' ' . $shop_identification;
1088 -
1089 - // The limit for the transaction text is 100. Ensure we don't go over. Thanks to Marco1970 on wp.org for reporting this. IOK 2019-10-17
1090 - $length = strlen($transaction['transactionText']);
1091 - if ($length>99) {
1092 - $this->log(__('The transaction text is too long! We are using a shorter transaction text to allow the transaction text to go through, but please check the \'woo_vipps_transaction_text_shop_id\' filter so that you can use a shorter name for your store', 'woo-vipps'));
1093 - $transaction['transactionText'] = __('Order capture for order','woo-vipps') . ' ' . $orderid;
1094 - $transaction['transactionText'] = substr($transaction['transactionText'],0,90); // Add some slack if this happens. IOK 2019-10-17
1095 - }
1096 -
1097 -
1098 -
1099 - $data = array();
1100 - $data['merchantInfo'] = array('merchantSerialNumber' => $msn);
1101 - $data['transaction'] = $transaction;
1102 -
1103 - $res = $this->http_call($msn,$command,$data,'POST',$headers,'json');
1104 - return $res;
1105 - }
1106 -
1107 - // Cancel a reserved but not captured payment IOK 2018-05-07
1108 - public function cancel_payment($order,$requestid=1) {
1109 - $orderid = $order->get_meta('_vipps_orderid');
1110 -
1111 - $command = 'Ecomm/v2/payments/'.$orderid.'/cancel';
1112 - $msn = $this->get_merchant_serial();
1113 - $subkey = $this->get_key($msn);
1114 - if (!$subkey) {
1115 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1116 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1117 - }
1118 - if (!$msn) {
1119 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1120 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1121 - }
1122 - $headers = $this->get_headers($msn);
1123 - $headers['X-Request-Id'] = $requestid;
1124 -
1125 - $transaction = array();
1126 - $transaction['transactionText'] = __('Order cancel for order','woo-vipps') . ' ' . $orderid . ' ';
1127 -
1128 - $data = array();
1129 - $data['merchantInfo'] = array('merchantSerialNumber' => $msn);
1130 - $data['transaction'] = $transaction;
1131 -
1132 - $res = $this->http_call($msn,$command,$data,'PUT',$headers,'json');
1133 - return $res;
1134 - }
1135 -
1136 - // Refund a captured payment. IOK 2018-05-08
1137 - public function refund_payment($order,$requestid=1,$amount=0,$cents=false) {
1138 - $orderid = $order->get_meta('_vipps_orderid');
1139 - $amount = $amount ? $amount : wc_format_decimal($order->get_total(),'');
1140 -
1141 - $command = 'Ecomm/v2/payments/'.$orderid.'/refund';
1142 - $msn = $this->get_merchant_serial();
1143 - $subkey = $this->get_key($msn);
1144 - if (!$subkey) {
1145 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1146 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1147 - }
1148 - if (!$msn) {
1149 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1150 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1151 - }
1152 - $headers = $this->get_headers($msn);
1153 - $headers['X-Request-Id'] = $requestid;
1154 -
1155 - // Ignore refOrderId - for child-transactions
1156 - $transaction = array();
1157 - // If we have passed the value as 'øre' we don't need to calculate any more.
1158 - if ($cents) {
1159 - $transaction['amount'] = $amount;
1160 - } else {
1161 - $transaction['amount'] = round($amount * 100);
1162 - }
1163 - $transaction['transactionText'] = __('Refund for order','woo-vipps') . ' ' . $orderid;
1164 -
1165 -
1166 - $data = array();
1167 - $data['merchantInfo'] = array('merchantSerialNumber' => $msn);
1168 - $data['transaction'] = $transaction;
1169 -
1170 - $res = $this->http_call($msn,$command,$data,'POST',$headers,'json');
1171 - return $res;
1172 - }
1173 -
1174 - // Used to retrieve shipping and user details for express checkout orders where relevant and the callback isn't coming.
1175 - public function payment_details ($order) {
1176 - $requestid=0;
1177 - $orderid = $order->get_meta('_vipps_orderid');
1178 - $command = 'Ecomm/v2/payments/'.$orderid.'/details';
1179 - $msn = $this->get_merchant_serial();
1180 - $subkey = $this->get_key($msn);
1181 - if (!$subkey) {
1182 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1183 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1184 - }
1185 - if (!$msn) {
1186 - throw new VippsAPIConfigurationException(__('The Vipps gateway is not correctly configured.','woo-vipps'));
1187 - $this->log(__('The Vipps gateway is not correctly configured.','woo-vipps'),'error');
1188 - }
1189 - $headers = $this->get_headers($msn);
1190 - $headers['X-Request-Id'] = $requestid;
1191 -
1192 - $data = array();
1193 -
1194 - $res = $this->http_call($msn,$command,$data,'GET',$headers,'json');
1195 - return $res;
1196 - }
1197 -
1198 1080 // Support for then new epayment API, which is also used by Checkout
1199 1081 // Cancel a reserved but not captured payment IOK 2018-05-07
1200 1082 // Currently must cancel the entire amount, but partial cancel will be possible.
1201 1083 public function epayment_cancel_payment($order,$requestid=1) {
@@ -1348,9 +1230,12 @@
1348 1230 return $res;
1349 1231 }
1350 1232
1351 1233 // Implement part of the userInfo api, just to be able to get user data from Express Orders that aren't express
1352 - // orders (because they didn't need shipping). In the future, will probably be used more + for integration with Login With Vipps
1234 + // orders (because they didn't need shipping).
1235 + // If a user has a sub, it is because we've added a scope to the epayment call, or because of integration with login.
1236 + // This is not used as of 2026-08-18, because we do not need to call this to retreive user details any more with ecom -
1237 + // we get that by just calling the payment details. Still may be useful in the future without depending on login integration. IOK 2026-08-18
1353 1238 public function get_userinfo($sub) {
1354 1239 $command = "vipps-userinfo-api/userinfo" . "/" . $sub;
1355 1240 $msn = $this->get_merchant_serial();
1356 1241 $subkey = $this->get_key($msn);
@@ -1387,9 +1272,9 @@
1387 1272 return $this->call_qr_merchant_redirect($action, $id, $url);
1388 1273 }
1389 1274 public function delete_merchant_redirect_qr ($id) {
1390 1275 $action = "DELETE";
1391 - return $this->call_qr_merchant_redirect($action, $id, $url);
1276 + return $this->call_qr_merchant_redirect($action, $id);
1392 1277 }
1393 1278 private function call_qr_merchant_redirect($action, $id, $url=null, $accept='image/svg+xml') {
1394 1279 $command = 'qr/v1/merchant-redirect/';
1395 1280 if ($action != "POST") $command .= $id;