| @@ -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); |
| @@ -934,10 +949,10 @@ | ||
| 934 | 949 | $configuration['customConsent'] = $customconsent; |
| 935 | 950 | } |
| 936 | 951 | |
| 937 | 952 | if (!$needs_shipping) { |
| 938 | - $nocontacts = $this->gateway->get_option('noContactFields') == 'yes'; | |
| 939 | - $noaddress = $this->gateway->get_option('noAddressFields') == 'yes'; | |
| 953 | + $nocontacts = (bool) ($this->gateway->get_option('noContactFields') == 'yes'); | |
| 954 | + $noaddress = (bool) ($this->gateway->get_option('noAddressFields') == 'yes'); | |
| 940 | 955 | if ($noaddress) { |
| 941 | 956 | $configuration['elements'] = "PaymentAndContactInfo"; |
| 942 | 957 | } |
| 943 | 958 | // AddressFields cannot be enabled while ContactFields is disabled |
| @@ -1059,143 +1074,9 @@ | ||
| 1059 | 1074 | } |
| 1060 | 1075 | return $res; |
| 1061 | 1076 | } |
| 1062 | 1077 | |
| 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 | 1078 | |
| 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 | 1079 | // Support for then new epayment API, which is also used by Checkout |
| 1199 | 1080 | // Cancel a reserved but not captured payment IOK 2018-05-07 |
| 1200 | 1081 | // Currently must cancel the entire amount, but partial cancel will be possible. |
| 1201 | 1082 | public function epayment_cancel_payment($order,$requestid=1) { |
| @@ -1348,9 +1229,12 @@ | ||
| 1348 | 1229 | return $res; |
| 1349 | 1230 | } |
| 1350 | 1231 | |
| 1351 | 1232 | // 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 | |
| 1233 | + // orders (because they didn't need shipping). | |
| 1234 | + // If a user has a sub, it is because we've added a scope to the epayment call, or because of integration with login. | |
| 1235 | + // 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 - | |
| 1236 | + // 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 | 1237 | public function get_userinfo($sub) { |
| 1354 | 1238 | $command = "vipps-userinfo-api/userinfo" . "/" . $sub; |
| 1355 | 1239 | $msn = $this->get_merchant_serial(); |
| 1356 | 1240 | $subkey = $this->get_key($msn); |