WooCommerce Square - Version 3.0.0

Version Description

  • 2022-05-04 =
  • New - Upgrade the payment form on checkout to use the latest Square Web Payments SDK. PR#668
  • Fix - Compatibility issues with WordPress 6.1.0. PR#715
  • Fix - Sync issues caused by product variations having an empty SKU and incorrectly being set to the variable product (parent product) SKU value. PR#764
  • Update - Remove admin notice warning of v3.0.0 release. PR#744
  • Dev - Product importing is now handled by Action Scheduler. PR#698
  • Dev - Syncing is now handled by Action Scheduler. PR#699
  • Dev - Manual Sync is now handled by Action Scheduler. PR#710
  • Dev - Upgrade Action Scheduler to 3.4.0. PR#762
  • Dev - Updated Square Connect to Square SDK v 15.0.0. PR#673 PR#670 PR#668 PR#664 PR#659 PR#657
  • Dev - Remove SkyVerge framework. PR#690 PR#689 PR#688 PR#687 PR#684 PR#683 PR#681 PR#678
Download this release

Release Info

Developer automattic
Plugin Icon 128x128 WooCommerce Square
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.9.1 to 3.0.0

Files changed (131) hide show
  1. assets/css/admin/wc-square-payment-gateway-admin-order.min.css +1 -0
  2. assets/css/admin/wc-square-payment-gateway-token-editor.min.css +1 -0
  3. assets/css/frontend/wc-square-digital-wallet.min.css +1 -1
  4. assets/css/frontend/wc-square-payment-gateway-my-payment-methods.min.css +1 -0
  5. assets/css/frontend/wc-square-payment-gateway-payment-form.min.css +1 -0
  6. vendor/skyverge/wc-plugin-framework/tests/_archive/integration/plugin.php → assets/css/mixins.min.css +0 -0
  7. {vendor/skyverge/wc-plugin-framework/woocommerce/assets → assets}/css/mixins.scss +0 -0
  8. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amazon.png +0 -0
  9. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amazon.svg +0 -0
  10. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amex.png +0 -0
  11. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amex.svg +0 -0
  12. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cartebleue.png +0 -0
  13. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cartebleue.svg +0 -0
  14. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-invalid.png +0 -0
  15. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-invalid.svg +0 -0
  16. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-plain.png +0 -0
  17. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-plain.svg +0 -0
  18. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cirrus.png +0 -0
  19. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cirrus.svg +0 -0
  20. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-dinersclub.png +0 -0
  21. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-dinersclub.svg +0 -0
  22. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-discover.png +0 -0
  23. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-discover.svg +0 -0
  24. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-echeck.png +0 -0
  25. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-echeck.svg +0 -0
  26. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-google.png +0 -0
  27. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-google.svg +0 -0
  28. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-jcb.png +0 -0
  29. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-jcb.svg +0 -0
  30. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-laser.png +0 -0
  31. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-laser.svg +0 -0
  32. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-maestro.png +0 -0
  33. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-maestro.svg +0 -0
  34. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-mastercard.png +0 -0
  35. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-mastercard.svg +0 -0
  36. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-moneybookers.png +0 -0
  37. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-moneybookers.svg +0 -0
  38. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-paypal.png +0 -0
  39. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-paypal.svg +0 -0
  40. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-solo.png +0 -0
  41. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-solo.svg +0 -0
  42. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-switch.png +0 -0
  43. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-switch.svg +0 -0
  44. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-debit.png +0 -0
  45. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-debit.svg +0 -0
  46. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-electron.png +0 -0
  47. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-electron.svg +0 -0
  48. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa.png +0 -0
  49. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa.svg +0 -0
  50. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/license.txt +0 -0
  51. {vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/sample-check.png +0 -0
  52. assets/js/admin/wc-square-admin-products.min.js +1 -1
  53. assets/js/admin/wc-square-admin-settings.min.js +1 -1
  54. assets/js/admin/wc-square-payment-gateway-admin-order.min.js +1 -0
  55. assets/js/admin/wc-square-payment-gateway-token-editor.min.js +1 -0
  56. assets/js/frontend/wc-square-digital-wallet.min.js +1 -1
  57. assets/js/frontend/wc-square-payment-gateway-apple-pay.min.js +1 -0
  58. assets/js/frontend/wc-square-payment-gateway-my-payment-methods.min.js +1 -0
  59. assets/js/frontend/wc-square-payment-gateway-payment-form.min.js +1 -0
  60. assets/js/frontend/wc-square.min.js +1 -1
  61. build/index.asset.php +1 -1
  62. build/index.js +1 -1
  63. changelog.txt +277 -0
  64. composer.json +0 -26
  65. i18n/languages/woocommerce-square.pot +1872 -1936
  66. includes/AJAX.php +3 -40
  67. includes/API.php +76 -91
  68. includes/API/Request.php +3 -6
  69. includes/API/Requests/Catalog.php +47 -57
  70. includes/API/Requests/Customers.php +3 -5
  71. includes/API/Requests/Inventory.php +33 -23
  72. includes/API/Requests/Locations.php +2 -7
  73. includes/API/Response.php +18 -11
  74. includes/API/Responses/Catalog.php +1 -2
  75. includes/API/Responses/Connection_Refresh_Response.php +2 -6
  76. includes/API/Responses/Inventory.php +2 -3
  77. includes/API/Responses/Locations.php +2 -4
  78. includes/Admin.php +0 -1
  79. includes/Admin/Privacy.php +0 -2
  80. includes/Admin/Settings_Page.php +0 -1
  81. includes/Admin/Sync_Page.php +0 -1
  82. includes/Emails/Access_Token_Email.php +0 -2
  83. includes/Emails/Base_Email.php +2 -2
  84. includes/Emails/Sync_Completed.php +7 -19
  85. includes/Framework/Addresses/Address.php +263 -0
  86. includes/Framework/Addresses/Customer_Address.php +128 -0
  87. includes/Framework/Admin_Message_Handler.php +392 -0
  88. includes/Framework/Admin_Notice_Handler.php +380 -0
  89. includes/Framework/Api/API_JSON_Request.php +105 -0
  90. includes/Framework/Api/API_JSON_Response.php +67 -0
  91. includes/Framework/Api/API_Request.php +62 -0
  92. includes/Framework/Api/API_Response.php +25 -0
  93. includes/Framework/Api/Base.php +659 -0
  94. includes/Framework/Compatibility/Data_Compatibility.php +114 -0
  95. includes/Framework/Compatibility/Order_Compatibility.php +243 -0
  96. includes/Framework/Lifecycle.php +550 -0
  97. includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php +434 -0
  98. includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php +668 -0
  99. includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_User_Handler.php +381 -0
  100. includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php +79 -0
  101. includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php +45 -0
  102. includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor-token.php +71 -0
  103. includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor.php +65 -0
  104. includes/Framework/PaymentGateway/Admin/views/html-user-profile-field-customer-id.php +7 -0
  105. includes/Framework/PaymentGateway/Admin/views/html-user-profile-section.php +25 -0
  106. includes/Framework/PaymentGateway/Api/Payment_Gateway_API_Response.php +91 -0
  107. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api.php +220 -0
  108. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Authorization_Response.php +55 -0
  109. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Create_Payment_Token_Response.php +22 -0
  110. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Customer_Response.php +19 -0
  111. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Get_Tokenized_Payment_Methods_Response.php +21 -0
  112. includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php +88 -0
  113. includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api.php +176 -0
  114. includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api_Request.php +96 -0
  115. includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api_Response.php +93 -0
  116. includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Payment_Response.php +189 -0
  117. includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php +1029 -0
  118. includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php +392 -0
  119. includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Ajax.php +240 -0
  120. includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php +340 -0
  121. includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php +178 -0
  122. includes/Framework/PaymentGateway/Handlers/Capture.php +400 -0
  123. includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration.php +43 -0
  124. includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php +351 -0
  125. includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php +673 -0
  126. includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Token.php +366 -0
  127. includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php +859 -0
  128. includes/Framework/PaymentGateway/Payment_Gateway.php +3813 -0
  129. includes/Framework/PaymentGateway/Payment_Gateway_Direct.php +1007 -0
  130. includes/Framework/PaymentGateway/Payment_Gateway_Helper.php +238 -0
  131. includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php +931 -0
assets/css/admin/wc-square-payment-gateway-admin-order.min.css ADDED
@@ -0,0 +1 @@
 
1
+ #woocommerce-order-items .sv-wc-payment-gateway-partial-capture .capture-actions{margin-top:5px;padding-top:12px;border-top:1px solid #dfdfdf}#woocommerce-order-items .sv-wc-payment-gateway-partial-capture .capture-actions .button{float:right;margin-left:4px}#woocommerce-order-items .sv-wc-payment-gateway-partial-capture .capture-actions .cancel-action{float:left;margin-left:0}
assets/css/admin/wc-square-payment-gateway-token-editor.min.css ADDED
@@ -0,0 +1 @@
 
1
+ table.sv_wc_payment_gateway_token_editor{width:auto}table.sv_wc_payment_gateway_token_editor th{padding:9px 7px!important;vertical-align:middle}table.sv_wc_payment_gateway_token_editor td{vertical-align:middle;padding:10px 7px;line-height:2em}table.sv_wc_payment_gateway_token_editor tr:nth-child(odd) td{background:#f9f9f9}table.sv_wc_payment_gateway_token_editor tr.token input.error{border-color:#a00}table.sv_wc_payment_gateway_token_editor .token-default{text-align:center}table.sv_wc_payment_gateway_token_editor .token-actions{text-align:right}table.sv_wc_payment_gateway_token_editor .actions{font-weight:400;text-align:right}table.sv_wc_payment_gateway_token_editor .actions .error{color:#a00;padding-right:10px;font-weight:700}
assets/css/frontend/wc-square-digital-wallet.min.css CHANGED
@@ -1 +1 @@
1
- #wc-square-digital-wallet{display:none;clear:both;padding-top:1.5em;width:100%;max-width:510px;margin:0 auto}#wc-square-wallet-divider{margin-top:1em;text-align:center}.wc-square-wallet-buttons{width:99%;height:44px;margin:0 0 1em 0;cursor:pointer;display:none}.wc-square-wallet-button-black{background-color:#000}.wc-square-wallet-button-white{background-color:#fff}.google-pay-button{padding:11px 10px;background-origin:content-box;background-position:center;background-repeat:no-repeat;background-size:contain;border:0;border-radius:4px;box-shadow:0 1px 1px 0 rgba(60,64,67,.3),0 1px 3px 1px rgba(60,64,67,.15);outline:0;cursor:pointer}.google-pay-button.wc-square-wallet-button-black{background-image:url(data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23FFF%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E)}.google-pay-button.wc-square-wallet-button-white{background-image:url(data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23000%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E)}@supports (-webkit-appearance:-apple-pay-button){.apple-pay-button{-webkit-appearance:-apple-pay-button;cursor:pointer}.apple-pay-button>*{display:none}}@supports not (-webkit-appearance:-apple-pay-button){.apple-pay-button{background-size:100% 60%;background-repeat:no-repeat;background-position:50% 50%;border-radius:5px;padding:0;box-sizing:border-box;min-width:200px;min-height:32px;max-height:64px;cursor:pointer}.apple-pay-button.wc-square-wallet-button-with-text{--apple-pay-scale:1;justify-content:center;font-size:12px;background:0 0}.apple-pay-button.wc-square-wallet-button-with-text .text{font-family:-apple-system;font-size:calc(1em * var(--apple-pay-scale));font-weight:300;align-self:center;margin-right:calc(2px * var(--apple-pay-scale))}.apple-pay-button.wc-square-wallet-button-with-text .logo{width:calc(35px * var(--scale));height:100%;background-size:100% 60%;background-repeat:no-repeat;background-position:0 50%;margin-left:calc(2px * var(--apple-pay-scale));border:none}.apple-pay-button.wc-square-wallet-button-black{background-color:#000;color:#fff}.apple-pay-button.wc-square-wallet-button-black .logo{background-image:-webkit-named-image(apple-pay-logo-white);background-color:#000}.apple-pay-button.wc-square-wallet-button-white{background-color:#fff;color:#000}.apple-pay-button.wc-square-wallet-button-white .logo{background-image:-webkit-named-image(apple-pay-logo-black);background-color:#fff}.apple-pay-button.wc-square-wallet-button-white-outline{background-color:#fff;color:#000;border:.5px solid #000}.apple-pay-button.wc-square-wallet-button-white-outline .logo{background-image:-webkit-named-image(apple-pay-logo-black);background-color:#fff}}
1
+ #wc-square-digital-wallet{display:none;clear:both;padding-top:1.5em;width:100%;max-width:510px;margin:0 auto}#wc-square-wallet-divider{margin-top:1em;text-align:center}.wc-square-wallet-buttons{height:40px;margin:0 0 1em 0;cursor:pointer;display:none}.wc-square-wallet-button-black{background-color:#000}.wc-square-wallet-button-white{background-color:#fff}.google-pay-button{padding:11px 10px;background-origin:content-box;background-position:center;background-repeat:no-repeat;background-size:contain;border:0;border-radius:4px;box-shadow:0 1px 1px 0 rgba(60,64,67,.3),0 1px 3px 1px rgba(60,64,67,.15);outline:0;cursor:pointer}.google-pay-button.wc-square-wallet-button-black{background-image:url(data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23FFF%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E)}.google-pay-button.wc-square-wallet-button-white{background-image:url(data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23000%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E)}@supports (-webkit-appearance:-apple-pay-button){.apple-pay-button{-webkit-appearance:-apple-pay-button;cursor:pointer}.apple-pay-button>*{display:none}}@supports not (-webkit-appearance:-apple-pay-button){.apple-pay-button{background-size:100% 60%;background-repeat:no-repeat;background-position:50% 50%;border-radius:5px;padding:0;box-sizing:border-box;min-width:200px;min-height:32px;max-height:64px;cursor:pointer}.apple-pay-button.wc-square-wallet-button-with-text{--apple-pay-scale:1;justify-content:center;font-size:12px;background:0 0}.apple-pay-button.wc-square-wallet-button-with-text .text{font-family:-apple-system;font-size:calc(1em * var(--apple-pay-scale));font-weight:300;align-self:center;margin-right:calc(2px * var(--apple-pay-scale))}.apple-pay-button.wc-square-wallet-button-with-text .logo{width:calc(35px * var(--scale));height:100%;background-size:100% 60%;background-repeat:no-repeat;background-position:0 50%;margin-left:calc(2px * var(--apple-pay-scale));border:none}.apple-pay-button.wc-square-wallet-button-black{background-color:#000;color:#fff}.apple-pay-button.wc-square-wallet-button-black .logo{background-image:-webkit-named-image(apple-pay-logo-white);background-color:#000}.apple-pay-button.wc-square-wallet-button-white{background-color:#fff;color:#000}.apple-pay-button.wc-square-wallet-button-white .logo{background-image:-webkit-named-image(apple-pay-logo-black);background-color:#fff}.apple-pay-button.wc-square-wallet-button-white-outline{background-color:#fff;color:#000;border:.5px solid #000}.apple-pay-button.wc-square-wallet-button-white-outline .logo{background-image:-webkit-named-image(apple-pay-logo-black);background-color:#fff}}
assets/css/frontend/wc-square-payment-gateway-my-payment-methods.min.css ADDED
@@ -0,0 +1 @@
 
1
+ table.sv-wc-payment-gateway-my-payment-methods-table{font-size:.85em}table.sv-wc-payment-gateway-my-payment-methods-table td,table.sv-wc-payment-gateway-my-payment-methods-table th{vertical-align:middle}table.sv-wc-payment-gateway-my-payment-methods-table .button{white-space:nowrap}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-actions span,table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-default span,table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-details span{display:none}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-default,table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-expiry{text-align:center}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-payment-method-header-actions{text-align:right}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-title input{width:100%}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-details{white-space:nowrap}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-details img{width:40px;height:25px;margin-right:.5em;vertical-align:middle;display:inline!important}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-expiry{text-align:center}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-default{text-align:center}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-default mark{display:inline-block;color:#fff;background-color:#3d9cd2;font-size:.75em;text-transform:uppercase;padding:2px 4px;border-radius:2px}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions{text-align:right}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions .button{margin:.125em 0 .125em .25em}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions .button.disabled.tip:hover{cursor:help}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .cancel-edit-payment-method{margin-right:.5em}table.sv-wc-payment-gateway-my-payment-methods-table.editing .sv-wc-payment-gateway-payment-method-header-default span{display:inline}table.sv-wc-payment-gateway-my-payment-methods-table.editing .sv-wc-payment-gateway-my-payment-methods-method:not(.editing),table.sv-wc-payment-gateway-my-payment-methods-table.editing .sv-wc-payment-gateway-my-payment-methods-type-divider{opacity:.5}table.sv-wc-payment-gateway-my-payment-methods-table.editing .sv-wc-payment-gateway-my-payment-methods-method:hover{opacity:1}table.sv-wc-payment-gateway-my-payment-methods-table tr.sv-wc-payment-gateway-my-payment-methods-type-divider td{font-weight:700}table.sv-wc-payment-gateway-my-payment-methods-table .error td{color:#fff;text-align:center;background-color:#e26838;border-radius:0 0 3px 3px;padding:5px}#tiptip_holder{display:none;position:absolute;top:0;left:0;z-index:99999}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-left:-6px;border-top-color:#464646}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-left:-6px;border-bottom-color:#464646}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-left:-5px;border-right-color:#464646}#tiptip_holder.tip_left{padding-right:5px}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-left:-7px;border-left-color:#464646}#tiptip_content,.chart-tooltip{font-size:11px;color:#fff;padding:.5em .5em;background:#464646;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:1px 1px 3px rgba(0,0,0,.1);-moz-box-shadow:1px 1px 3px rgba(0,0,0,.1);box-shadow:1px 1px 3px rgba(0,0,0,.1);text-align:center;max-width:150px}#tiptip_content code,.chart-tooltip code{background:#888;padding:1px}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}@media screen and (max-width:768px){table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-default,table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-expiry{text-align:right}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions{text-align:right}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions:before{display:none}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-method .sv-wc-payment-gateway-payment-method-actions .button{float:none;margin:.125em .25em .125em 0}table.sv-wc-payment-gateway-my-payment-methods-table .sv-wc-payment-gateway-my-payment-methods-type-divider td:before{display:none}}
assets/css/frontend/wc-square-payment-gateway-payment-form.min.css ADDED
@@ -0,0 +1 @@
 
1
+ #add_payment_method .sv-wc-payment-gateway-payment-form-manage-payment-methods,.woocommerce-checkout #payment div.payment_box .sv-wc-payment-gateway-payment-form-manage-payment-methods{display:block;margin:1em 0;text-align:center}#add_payment_method .sv-wc-payment-gateway-payment-form-saved-payment-method,.woocommerce-checkout #payment div.payment_box .sv-wc-payment-gateway-payment-form-saved-payment-method{display:inline-block;margin-bottom:.5em}#add_payment_method .sv-wc-payment-gateway-payment-form-saved-payment-method .nickname,.woocommerce-checkout #payment div.payment_box .sv-wc-payment-gateway-payment-form-saved-payment-method .nickname{margin-right:.5em}#add_payment_method .sv-wc-payment-gateway-payment-form-saved-payment-method img,.woocommerce-checkout #payment div.payment_box .sv-wc-payment-gateway-payment-form-saved-payment-method img{float:none;width:30px;height:20px;display:inline-block;margin-right:.5em;vertical-align:middle}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel],#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=text],#add_payment_method input.js-sv-wc-payment-gateway-echeck-form-input[type=tel],#add_payment_method input.js-sv-wc-payment-gateway-echeck-form-input[type=text],#add_payment_method input.js-sv-wc-payment-gateway-form-nickname,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel],.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=text],.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-echeck-form-input[type=tel],.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-echeck-form-input[type=text],.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-form-nickname{font-size:1.5em;padding:8px}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel]:focus,#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=text]:focus,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel]:focus,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=text]:focus{box-shadow:0 0 .1875em #3498db}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel].identified,#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=text].identified,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel].identified,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=text].identified{border-color:#69bf29}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel].identified:focus,#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-input[type=text].identified:focus,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=tel].identified:focus,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-input[type=text].identified:focus{box-shadow:0 0 .1875em #69bf29}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number{background-image:url(../../images/card-cc-plain.svg);background-repeat:no-repeat;background-position:right 10px center;background-size:50px 31px}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.visa,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.visa{background-image:url(../../images/card-visa.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.mastercard,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.mastercard{background-image:url(../../images/card-mastercard.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.dinersclub,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.dinersclub{background-image:url(../../images/card-dinersclub.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.maestro,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.maestro{background-image:url(../../images/card-maestro.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.jcb,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.jcb{background-image:url(../../images/card-jcb.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.amex,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.amex{background-image:url(../../images/card-amex.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.discover,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.discover{background-image:url(../../images/card-discover.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.visaelectron,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.visaelectron{background-image:url(../../images/card-visa-electron.svg)}#add_payment_method input.js-sv-wc-payment-gateway-credit-card-form-account-number.invalid-card-type,.woocommerce-checkout #payment div.payment_box input.js-sv-wc-payment-gateway-credit-card-form-account-number.invalid-card-type{background-image:url(../../images/card-cc-invalid.svg)}#add_payment_method .js-sv-wc-payment-gateway-echeck-form-check-hint,.woocommerce-checkout #payment div.payment_box .js-sv-wc-payment-gateway-echeck-form-check-hint{margin:0 0 3px 2px;cursor:pointer}#add_payment_method .js-sv-wc-payment-gateway-echeck-form-sample-check,.woocommerce-checkout #payment div.payment_box .js-sv-wc-payment-gateway-echeck-form-sample-check{margin:1em}#add_payment_method .js-sv-wc-payment-gateway-echeck-form-sample-check img,.woocommerce-checkout #payment div.payment_box .js-sv-wc-payment-gateway-echeck-form-sample-check img{min-height:135px}#add_payment_method ul.payment_methods li{list-style-type:none}#add_payment_method ul.payment_methods li img{vertical-align:middle;margin:-2px 0 0 .5em;padding:0;position:relative;box-shadow:none}#add_payment_method ul.payment_methods li img+img{margin-left:2px}
vendor/skyverge/wc-plugin-framework/tests/_archive/integration/plugin.php → assets/css/mixins.min.css RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/assets → assets}/css/mixins.scss RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amazon.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amazon.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amex.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-amex.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cartebleue.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cartebleue.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-invalid.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-invalid.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-plain.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cc-plain.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cirrus.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-cirrus.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-dinersclub.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-dinersclub.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-discover.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-discover.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-echeck.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-echeck.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-google.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-google.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-jcb.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-jcb.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-laser.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-laser.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-maestro.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-maestro.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-mastercard.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-mastercard.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-moneybookers.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-moneybookers.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-paypal.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-paypal.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-solo.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-solo.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-switch.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-switch.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-debit.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-debit.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-electron.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa-electron.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa.png RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/card-visa.svg RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/license.txt RENAMED
File without changes
{vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/assets → assets}/images/sample-check.png RENAMED
File without changes
assets/js/admin/wc-square-admin-products.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";jQuery(document).ready(function($){var typenow=window.typenow||"";var pagenow=window.pagenow||"";if("product"!==typenow){return}if(!wc_square_admin_products.is_product_sync_enabled){return}if("edit-product"===pagenow){$("#the-list").on("click",".editinline",function(e){var $row=$(e.target).closest("tr");var postID=$row.find("th.check-column input").val();var data={action:"wc_square_get_quick_edit_product_details",security:wc_square_admin_products.get_quick_edit_product_details_nonce,product_id:$row.find("th.check-column input").val()};$.post(wc_square_admin_products.ajax_url,data,function(response){var $editRow=$("tr#edit-"+postID);var $squareSynced=$editRow.find("select.square-synced");var $errors=$editRow.find(".wc-square-sync-with-square-errors");if(!response.success&&response.data){if("multiple_attributes"===response.data){$squareSynced.prop("checked",false);$squareSynced.prop("disabled",true);$errors.find(".multiple_attributes").show();return}else if("missing_variation_sku"===response.data){$squareSynced.prop("checked",false);$squareSynced.prop("disabled",true);$errors.find(".missing_variation_sku").show();return}}var $sku=$editRow.find("input[name=_sku]");var $stockStatus=$editRow.find("select[name=_stock_status]");var $stockQty=$editRow.find("input[name=_stock]");var $manageStockLabel=$editRow.find(".manage_stock_field .manage_stock");var $manageStockInput=$editRow.find("input[name=_manage_stock]");var $manageStockDesc="<span class=\"description\"><a href=\""+wc_square_admin_products.settings_url+"\">"+wc_square_admin_products.i18n.synced_with_square+"</a></span>";var edit_url=response.data.edit_url;var i18n=response.data.i18n;var is_variable=response.data.is_variable;$squareSynced.val(response.data.is_synced_with_square);$sku.on("change keyup keypress",function(e){if(""===$(e.target).val()&&!is_variable){$squareSynced.val("no").trigger("change");$squareSynced.prop("disabled",true);$errors.find(".missing_sku").show()}else{$squareSynced.prop("disabled",false);$squareSynced.trigger("change");return $errors.find(".missing_sku").hide()}}).trigger("change");$squareSynced.on("change",function(e){if("no"===$(e.target).val()){$manageStockInput.off();$manageStockInput.add($stockQty).css({opacity:1});$manageStockLabel.find(".description").remove();if(is_variable){if($manageStockInput.is(":checked")){$(".stock_qty_field").show();$(".backorder_field").show()}else{$(".stock_status_field").show()}}else{$stockQty.prop("readonly",false);$stockStatus.prop("readonly",false)}}else{$manageStockInput.prop("checked",true);$manageStockInput.on("click",function(){return false});$manageStockInput.add($stockQty).css({opacity:"0.5"});$manageStockLabel.append($manageStockDesc);if(wc_square_admin_products.is_woocommerce_sor&&edit_url&&i18n){$manageStockLabel.append("<p class=\"description\"><a href=\""+edit_url+"\">"+i18n+"</a></p>")}if(is_variable){$(".stock_status_field").hide();$(".stock_qty_field").hide();$(".backorder_field").hide()}else{$stockQty.prop("readonly",true);$stockStatus.prop("readonly",true)}}}).trigger("change")})})}if("product"===pagenow){var syncCheckboxID="#_"+wc_square_admin_products.synced_with_square_taxonomy;var isVariable=function isVariable(){return wc_square_admin_products.variable_product_types.includes($("#product-type").val())};var hasSKU=function hasSKU(){return""!==$("#_sku").val().trim()};var hasVariableSKUs=function hasVariableSKUs(skus){if(!skus.length){return false}var valid=skus.filter(function(sku){return""!==$(sku).val().trim()});return valid.length===skus.length};var hasUniqueSKUs=function hasUniqueSKUs(skus){var skuValues=skus.map(function(sku){return $(sku).val()});return skuValues.every(function(sku){return skuValues.indexOf(sku)===skuValues.lastIndexOf(sku)})};var hasMultipleAttributes=function hasMultipleAttributes(){var $variation_attributes=$(".woocommerce_attribute_data input[name^=\"attribute_variation\"]:checked");return isVariable()&&$variation_attributes&&$variation_attributes.length>1};var showError=function showError(error){$(".wc-square-sync-with-square-error."+error).show();$(syncCheckboxID).prop("disabled",true);$(syncCheckboxID).prop("checked",false)};var hideError=function hideError(error){var enable=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;$(".wc-square-sync-with-square-error."+error).hide();if(enable){$(syncCheckboxID).prop("disabled",false)}};var handleSKU=function handleSKU(syncCheckboxID){if(isVariable()){$("#_sku").off("change keypress keyup");hideError("missing_sku",!hasMultipleAttributes());var skus=$("input[id^=\"variable_sku\"]");skus.on("change keypress keyup",function(){if(!hasVariableSKUs($.makeArray(skus))||!hasUniqueSKUs($.makeArray(skus))){showError("missing_variation_sku")}else{hideError("missing_variation_sku",!hasMultipleAttributes())}$(syncCheckboxID).triggerHandler("change")}).triggerHandler("change")}else{$("input[id^=\"variable_sku\"]").off("change keypress keyup");hideError("missing_variation_sku",!hasMultipleAttributes());$("#_sku").on("change keypress keyup",function(e){if(""===$(e.target).val().trim()){showError("missing_sku")}else{hideError("missing_sku",!hasMultipleAttributes())}$(syncCheckboxID).trigger("change")}).trigger("change")}};var handleAttributes=function handleAttributes(syncCheckboxID){$("#variable_product_options").on("reload",function(){if(hasMultipleAttributes()){showError("multiple_attributes")}else{hideError("multiple_attributes",isVariable()?hasVariableSKUs:hasSKU())}$(syncCheckboxID).trigger("change")}).trigger("reload")};var triggerUpdate=function triggerUpdate(){handleSKU(syncCheckboxID);$(syncCheckboxID).trigger("change");if(isVariable()&&!$("input[id^=\"variable_sku\"]").length){showError("missing_variation_sku")}};handleAttributes(syncCheckboxID);var $stockFields=$(".stock_fields");var $stockInput=$stockFields.find("#_stock");var $stockStatus=$(".stock_status_field");var $manageField=$("._manage_stock_field");var $manageInput=$manageField.find("#_manage_stock");var $manageDesc=$manageField.find(".description");var manageDescOriginal=$manageDesc.text();var manageStockOriginal=$("#_manage_stock").is(":checked");$(syncCheckboxID).on("change",function(e){if(!wc_square_admin_products.is_inventory_sync_enabled){return}var variableProduct=wc_square_admin_products.variable_product_types.includes($("#product-type").val());var useSquare;if($(e.target).is(":checked")&&$("#_square_item_variation_id").length>0){useSquare=true;$manageDesc.html("<a href=\""+wc_square_admin_products.settings_url+"\">"+wc_square_admin_products.i18n.synced_with_square+"</a>");$manageInput.prop("disabled",true).prop("checked",!variableProduct);$stockFields.hide();$stockStatus.hide();$stockInput.prop("readonly",true);if(!variableProduct){$stockFields.show()}if(wc_square_admin_products.is_woocommerce_sor&&!variableProduct){if($("p._stock_field span.description").length===0){$stockInput.after("<span class=\"description\" style=\"display:block;clear:both;\"><a href=\"#\" id=\"fetch-stock-with-square\">"+wc_square_admin_products.i18n.fetch_stock_with_square+"</a><div class=\"spinner\" style=\"float:none;\"></div></span>")}$("#fetch-stock-with-square").on("click",function(e){e.preventDefault();var $spinner=$("p._stock_field span.description .spinner");var data={action:"wc_square_fetch_product_stock_with_square",security:wc_square_admin_products.fetch_product_stock_with_square_nonce,product_id:$("#post_ID").val()};$spinner.css("visibility","visible");$.post(wc_square_admin_products.ajax_url,data,function(response){if(response&&response.success){var quantity=response.data;$stockInput.val(quantity);$stockFields.find("input[name=_original_stock]").val(quantity);$stockInput.prop("readonly",false);$("p._stock_field span.description").remove()}else{if(response.data){$(".inventory-fetch-error").remove();$spinner.after("<span class=\"inventory-fetch-error\" style=\"display:inline-block;color:red;\">"+response.data+"</span>")}$spinner.css("visibility","hidden")}})})}else if(wc_square_admin_products.is_square_sor){if($("p._stock_field span.description").length===0){$stockInput.after("<span class=\"description\" style=\"display:block;clear:both;\">"+wc_square_admin_products.i18n.managed_by_square+"</span>")}}}else{useSquare=false;$("p._stock_field span.description").remove();$stockInput.prop("readonly",false);$manageDesc.html(manageDescOriginal);$manageInput.prop("disabled",false).prop("checked",manageStockOriginal);if(manageStockOriginal){$stockFields.show();$stockStatus.hide()}else{$stockStatus.show();$stockFields.hide()}}$(".woocommerce_variation").each(function(index,e){var variationID=$(e).find("h3 > a").attr("rel");var $variationManageInput=$(e).find(".variable_manage_stock");var $variationManageField=$variationManageInput.parent();var $variationStockInput=$(e).find(".wc_input_stock");var $variationStockField=$variationStockInput.parent();if(useSquare){$("#wc_square_variation_manage_stock").prop("disabled",false);$variationStockInput.prop("readonly",true);$variationManageInput.prop("disabled",true).prop("checked",true);if(0===$variationManageField.find(".description").length){$variationManageInput.after("<span class=\"description\">("+wc_square_admin_products.i18n.managed_by_square+")</span>")}if(wc_square_admin_products.is_woocommerce_sor){var fetchVariationStockActionID="fetch-stock-with-square-"+variationID;if(0===$variationStockField.find("span.description").length){$variationStockInput.after("<span class=\"description\" style=\"display:block;clear:both;\"><a href=\"#\" id=\""+fetchVariationStockActionID+"\">"+wc_square_admin_products.i18n.fetch_stock_with_square+"</a><div class=\"spinner\" style=\"float:none;\"></div></span>")}$("#"+fetchVariationStockActionID).on("click",function(e){e.preventDefault();var $spinner=$(e.target).next(".spinner");var data={action:"wc_square_fetch_product_stock_with_square",security:wc_square_admin_products.fetch_product_stock_with_square_nonce,product_id:variationID};$spinner.css("visibility","visible");$.post(wc_square_admin_products.ajax_url,data,function(response){if(response&&response.success){var quantity=response.data;$variationStockInput.val(quantity);$variationStockField.parent().find("input[name^=\"variable_original_stock\"]").val(quantity);$variationStockInput.prop("readonly",false);$variationStockField.find(".description").remove()}else{if(response.data){$(".inventory-fetch-error").remove();$spinner.after("<span class=\"inventory-fetch-error\" style=\"display:inline-block;color:red;\">"+response.data+"</span>")}$spinner.css("visibility","hidden")}})})}}else{$variationStockInput.prop("readonly",false);$variationManageInput.prop("disabled",false);$variationManageInput.next(".description").remove();$(e.target).find("#wc_square_variation_manage_stock").prop("disabled",true)}})}).trigger("change");$("#product-type").on("change",function(){triggerUpdate()});$("#woocommerce-product-data").on("woocommerce_variations_loaded woocommerce_variations_added woocommerce_variations_removed",function(){triggerUpdate()})}});
1
+ "use strict";jQuery(document).ready($=>{var typenow=window.typenow||"";var pagenow=window.pagenow||"";if("product"!==typenow){return}if(!wc_square_admin_products.is_product_sync_enabled){return}if("edit-product"===pagenow){$("#the-list").on("click",".editinline",e=>{var $row=$(e.target).closest("tr");var postID=$row.find("th.check-column input").val();var data={action:"wc_square_get_quick_edit_product_details",security:wc_square_admin_products.get_quick_edit_product_details_nonce,product_id:$row.find("th.check-column input").val()};$.post(wc_square_admin_products.ajax_url,data,response=>{var $editRow=$("tr#edit-"+postID);var $squareSynced=$editRow.find("select.square-synced");var $errors=$editRow.find(".wc-square-sync-with-square-errors");if(!response.success&&response.data){if("multiple_attributes"===response.data){$squareSynced.prop("checked",false);$squareSynced.prop("disabled",true);$errors.find(".multiple_attributes").show();return}else if("missing_variation_sku"===response.data){$squareSynced.prop("checked",false);$squareSynced.prop("disabled",true);$errors.find(".missing_variation_sku").show();return}}var $sku=$editRow.find("input[name=_sku]");var $stockStatus=$editRow.find("select[name=_stock_status]");var $stockQty=$editRow.find("input[name=_stock]");var $manageStockLabel=$editRow.find(".manage_stock_field .manage_stock");var $manageStockInput=$editRow.find("input[name=_manage_stock]");var $manageStockDesc="<span class=\"description\"><a href=\""+wc_square_admin_products.settings_url+"\">"+wc_square_admin_products.i18n.synced_with_square+"</a></span>";var edit_url=response.data.edit_url;var i18n=response.data.i18n;var is_variable=response.data.is_variable;$squareSynced.val(response.data.is_synced_with_square);$sku.on("change keyup keypress",e=>{if(""===$(e.target).val()&&!is_variable){$squareSynced.val("no").trigger("change");$squareSynced.prop("disabled",true);$errors.find(".missing_sku").show()}else{$squareSynced.prop("disabled",false);$squareSynced.trigger("change");return $errors.find(".missing_sku").hide()}}).trigger("change");$squareSynced.on("change",e=>{if("no"===$(e.target).val()){$manageStockInput.off();$manageStockInput.add($stockQty).css({opacity:1});$manageStockLabel.find(".description").remove();if(is_variable){if($manageStockInput.is(":checked")){$(".stock_qty_field").show();$(".backorder_field").show()}else{$(".stock_status_field").show()}}else{$stockQty.prop("readonly",false);$stockStatus.prop("readonly",false)}}else{$manageStockInput.prop("checked",true);$manageStockInput.on("click",()=>{return false});$manageStockInput.add($stockQty).css({opacity:"0.5"});$manageStockLabel.append($manageStockDesc);if(wc_square_admin_products.is_woocommerce_sor&&edit_url&&i18n){$manageStockLabel.append("<p class=\"description\"><a href=\""+edit_url+"\">"+i18n+"</a></p>")}if(is_variable){$(".stock_status_field").hide();$(".stock_qty_field").hide();$(".backorder_field").hide()}else{$stockQty.prop("readonly",true);$stockStatus.prop("readonly",true)}}}).trigger("change")})})}if("product"===pagenow){var syncCheckboxID="#_"+wc_square_admin_products.synced_with_square_taxonomy;var isVariable=()=>{return wc_square_admin_products.variable_product_types.includes($("#product-type").val())};var hasSKU=()=>{return""!==$("#_sku").val().trim()};var hasVariableSKUs=skus=>{if(!skus.length){return false}var valid=skus.filter(sku=>""!==$(sku).val().trim());return valid.length===skus.length};var hasUniqueSKUs=skus=>{var skuValues=skus.map(sku=>$(sku).val());return skuValues.every(sku=>skuValues.indexOf(sku)===skuValues.lastIndexOf(sku))};var hasMultipleAttributes=()=>{var $variation_attributes=$(".woocommerce_attribute_data input[name^=\"attribute_variation\"]:checked");return isVariable()&&$variation_attributes&&$variation_attributes.length>1};var showError=error=>{$(".wc-square-sync-with-square-error."+error).show();$(syncCheckboxID).prop("disabled",true);$(syncCheckboxID).prop("checked",false)};var hideError=function hideError(error){var enable=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;$(".wc-square-sync-with-square-error."+error).hide();if(enable){$(syncCheckboxID).prop("disabled",false)}};var handleSKU=syncCheckboxID=>{if(isVariable()){$("#_sku").off("change keypress keyup");hideError("missing_sku",!hasMultipleAttributes());var skus=$("input[id^=\"variable_sku\"]");skus.on("change keypress keyup",()=>{if(!hasVariableSKUs($.makeArray(skus))||!hasUniqueSKUs($.makeArray(skus))){showError("missing_variation_sku")}else{hideError("missing_variation_sku",!hasMultipleAttributes())}$(syncCheckboxID).triggerHandler("change")}).triggerHandler("change")}else{$("input[id^=\"variable_sku\"]").off("change keypress keyup");hideError("missing_variation_sku",!hasMultipleAttributes());$("#_sku").on("change keypress keyup",e=>{if(""===$(e.target).val().trim()){showError("missing_sku")}else{hideError("missing_sku",!hasMultipleAttributes())}$(syncCheckboxID).trigger("change")}).trigger("change")}};var handleAttributes=syncCheckboxID=>{$("#variable_product_options").on("reload",()=>{if(hasMultipleAttributes()){showError("multiple_attributes")}else{hideError("multiple_attributes",isVariable()?hasVariableSKUs:hasSKU())}$(syncCheckboxID).trigger("change")}).trigger("reload")};var triggerUpdate=()=>{handleSKU(syncCheckboxID);$(syncCheckboxID).trigger("change");if(isVariable()&&!$("input[id^=\"variable_sku\"]").length){showError("missing_variation_sku")}};handleAttributes(syncCheckboxID);var $stockFields=$(".stock_fields");var $stockInput=$stockFields.find("#_stock");var $stockStatus=$(".stock_status_field");var $manageField=$("._manage_stock_field");var $manageInput=$manageField.find("#_manage_stock");var $manageDesc=$manageField.find(".description");var manageDescOriginal=$manageDesc.text();var manageStockOriginal=$("#_manage_stock").is(":checked");$(syncCheckboxID).on("change",e=>{if(!wc_square_admin_products.is_inventory_sync_enabled){return}var variableProduct=wc_square_admin_products.variable_product_types.includes($("#product-type").val());var useSquare;if($(e.target).is(":checked")&&$("#_square_item_variation_id").length>0){useSquare=true;$manageDesc.html("<a href=\""+wc_square_admin_products.settings_url+"\">"+wc_square_admin_products.i18n.synced_with_square+"</a>");$manageInput.prop("disabled",true).prop("checked",!variableProduct);$stockFields.hide();$stockStatus.hide();$stockInput.prop("readonly",true);if(!variableProduct){$stockFields.show()}if(wc_square_admin_products.is_woocommerce_sor&&!variableProduct){if($("p._stock_field span.description").length===0){$stockInput.after("<span class=\"description\" style=\"display:block;clear:both;\"><a href=\"#\" id=\"fetch-stock-with-square\">"+wc_square_admin_products.i18n.fetch_stock_with_square+"</a><div class=\"spinner\" style=\"float:none;\"></div></span>")}$("#fetch-stock-with-square").on("click",e=>{e.preventDefault();var $spinner=$("p._stock_field span.description .spinner");var data={action:"wc_square_fetch_product_stock_with_square",security:wc_square_admin_products.fetch_product_stock_with_square_nonce,product_id:$("#post_ID").val()};$spinner.css("visibility","visible");$.post(wc_square_admin_products.ajax_url,data,response=>{if(response&&response.success){var quantity=response.data;$stockInput.val(quantity);$stockFields.find("input[name=_original_stock]").val(quantity);$stockInput.prop("readonly",false);$("p._stock_field span.description").remove()}else{if(response.data){$(".inventory-fetch-error").remove();$spinner.after("<span class=\"inventory-fetch-error\" style=\"display:inline-block;color:red;\">"+response.data+"</span>")}$spinner.css("visibility","hidden")}})})}else if(wc_square_admin_products.is_square_sor){if($("p._stock_field span.description").length===0){$stockInput.after("<span class=\"description\" style=\"display:block;clear:both;\">"+wc_square_admin_products.i18n.managed_by_square+"</span>")}}}else{useSquare=false;$("p._stock_field span.description").remove();$stockInput.prop("readonly",false);$manageDesc.html(manageDescOriginal);$manageInput.prop("disabled",false).prop("checked",manageStockOriginal);if(manageStockOriginal){$stockFields.show();$stockStatus.hide()}else{$stockStatus.show();$stockFields.hide()}}$(".woocommerce_variation").each((index,e)=>{var variationID=$(e).find("h3 > a").attr("rel");var $variationManageInput=$(e).find(".variable_manage_stock");var $variationManageField=$variationManageInput.parent();var $variationStockInput=$(e).find(".wc_input_stock");var $variationStockField=$variationStockInput.parent();if(useSquare){$("#wc_square_variation_manage_stock").prop("disabled",false);$variationStockInput.prop("readonly",true);$variationManageInput.prop("disabled",true).prop("checked",true);if(0===$variationManageField.find(".description").length){$variationManageInput.after("<span class=\"description\">("+wc_square_admin_products.i18n.managed_by_square+")</span>")}if(wc_square_admin_products.is_woocommerce_sor){var fetchVariationStockActionID="fetch-stock-with-square-"+variationID;if(0===$variationStockField.find("span.description").length){$variationStockInput.after("<span class=\"description\" style=\"display:block;clear:both;\"><a href=\"#\" id=\""+fetchVariationStockActionID+"\">"+wc_square_admin_products.i18n.fetch_stock_with_square+"</a><div class=\"spinner\" style=\"float:none;\"></div></span>")}$("#"+fetchVariationStockActionID).on("click",e=>{e.preventDefault();var $spinner=$(e.target).next(".spinner");var data={action:"wc_square_fetch_product_stock_with_square",security:wc_square_admin_products.fetch_product_stock_with_square_nonce,product_id:variationID};$spinner.css("visibility","visible");$.post(wc_square_admin_products.ajax_url,data,response=>{if(response&&response.success){var quantity=response.data;$variationStockInput.val(quantity);$variationStockField.parent().find("input[name^=\"variable_original_stock\"]").val(quantity);$variationStockInput.prop("readonly",false);$variationStockField.find(".description").remove()}else{if(response.data){$(".inventory-fetch-error").remove();$spinner.after("<span class=\"inventory-fetch-error\" style=\"display:inline-block;color:red;\">"+response.data+"</span>")}$spinner.css("visibility","hidden")}})})}}else{$variationStockInput.prop("readonly",false);$variationManageInput.prop("disabled",false);$variationManageInput.next(".description").remove();$(e.target).find("#wc_square_variation_manage_stock").prop("disabled",true)}})}).trigger("change");$("#product-type").on("change",()=>{triggerUpdate()});$("#woocommerce-product-data").on("woocommerce_variations_loaded woocommerce_variations_added woocommerce_variations_removed",()=>{triggerUpdate()})}});
assets/js/admin/wc-square-admin-settings.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";jQuery(document).ready(function($){var pagenow=window.pagenow||"";if("woocommerce_page_wc-settings"!==pagenow){return}if(!wc_square_admin_settings.is_sandbox){$("#wc_square_sandbox_settings").hide();$("#wc_square_sandbox_settings").next().hide();$(".wc_square_sandbox_settings").closest("tr").hide()}$("#wc_square_system_of_record").on("change",function(e){var system_of_record=$(e.target).val();var $inventory_sync=$("#wc_square_enable_inventory_sync");var $inventory_sync_row=$inventory_sync.closest("tr");if("square"===system_of_record||"woocommerce"===system_of_record){$inventory_sync.next("span").html(wc_square_admin_settings.i18n.sync_inventory_label[system_of_record]);$inventory_sync_row.find(".description").html(wc_square_admin_settings.i18n.sync_inventory_description[system_of_record]);$inventory_sync_row.show()}else{$inventory_sync.prop("checked",false);$inventory_sync_row.hide()}if("square"===system_of_record){$("#wc_square_hide_missing_products").closest("tr").show()}else{$("#wc_square_hide_missing_products").closest("tr").hide()}}).trigger("change");$(".js-import-square-products").on("click",function(e){e.preventDefault();new $.WCBackboneModal.View({target:"wc-square-import-products"});$("#btn-close").on("click",function(e){e.preventDefault();$("button.modal-close").trigger("click")})});$("#wc-square-sync").on("click",function(e){e.preventDefault();new $.WCBackboneModal.View({target:"wc-square-sync"});$("#btn-close").on("click",function(e){e.preventDefault();$("button.modal-close").trigger("click")})});$(document.body).on("wc_backbone_modal_response",function(e,target){var data;switch(target){case"wc-square-import-products":$("#wpbody").block({message:null,overlayCSS:{opacity:"0.2"},onBlock:function onBlock(){$(".blockUI.blockOverlay").css({position:"fixed"})}});var update_during_import=$("#wc-square-import-product-updates").prop("checked");data={action:"wc_square_import_products_from_square",dispatch:wc_square_admin_settings.sync_in_background,security:wc_square_admin_settings.import_products_from_square,update_during_import:update_during_import};$.post(wc_square_admin_settings.ajax_url,data,function(response){var message=response.data?response.data:null;if(message){alert(message)}location.reload()});break;case"wc-square-sync":$("table.sync").block({message:null,overlayCSS:{opacity:"0.2"}});$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});$("#wc-square_clear-sync-records").prop("disabled",true);data={action:"wc_square_sync_products_with_square",dispatch:wc_square_admin_settings.sync_in_background,security:wc_square_admin_settings.sync_products_with_square};$.post(wc_square_admin_settings.ajax_url,data,function(response){if(response&&response.success){location.reload()}else{$("#wc-square_clear-sync-records").prop("disabled",false);$("table.sync").unblock();$("table.records").unblock()}});break;}});var noRecordsFoundRow="<tr><td colspan=\"4\"><em>"+wc_square_admin_settings.i18n.no_records_found+"</em></td></tr>";$("#wc-square_clear-sync-records").on("click",function(e){e.preventDefault();$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});var data={action:"wc_square_handle_sync_records",id:"all",handle:"delete",security:wc_square_admin_settings.handle_sync_with_square_records};$.post(wc_square_admin_settings.ajax_url,data,function(response){if(response&&response.success){$("table.records tbody").html(noRecordsFoundRow);$("#wc-square_clear-sync-records").prop("disabled",true)}else{if(response.data){alert(response.data)}console.log(response)}$("table.records").unblock()})});$(".records .actions button.action").on("click",function(e){e.preventDefault();$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});var recordId=$(e.currentTarget).data("id");var action=$(e.currentTarget).data("action");var data={action:"wc_square_handle_sync_records",id:recordId,handle:action,security:wc_square_admin_settings.handle_sync_with_square_records};$.post(wc_square_admin_settings.ajax_url,data,function(response){if(response&&response.success){var rowId="#record-"+recordId;if("delete"===action){$(rowId).remove();if(!$("table.records tbody tr").length){$("table.records tbody").html(noRecordsFoundRow);$("#wc-square_clear-sync-records").prop("disabled",true)}}else if("resolve"===action||"unsync"===action){$(rowId+" .type").html("<mark class=\"resolved\"><span>"+wc_square_admin_settings.i18n.resolved+"</span></mark>");$(rowId+" .actions").html("&mdash;")}}else{if(response&&response.data){alert(response.data)}console.log({record:recordId,action:action,response:response})}$("table.records").unblock()})});$("form").on("submit",function(e){var environment=$("#wc_square_enable_sandbox").is(":checked")?"sandbox":"production";$(e.target).append($("<input>",{type:"hidden",name:"wc_square_environment",value:environment}))});var getSyncStatus=function getSyncStatus(job_id){var $progress=$("span.progress");if(!$progress||0===$progress.length){$("p.sync-result").append(" <span class=\"progress\" style=\"display:block\"></span>");$progress=$("span.progress")}var data={action:"wc_square_get_sync_with_square_status",security:wc_square_admin_settings.get_sync_with_square_status_nonce,job_id:job_id};$.post(wc_square_admin_settings.ajax_url,data,function(response){if(response&&response.data){if(response.success&&response.data.id){$("table.sync .spinner").css("visibility","visible");$("#wc-square_clear-sync-records").prop("disabled",true);$("table.records .actions button").prop("disabled",true);if("completed"!==response.data.status&&"failed"!==response.data.status){var progress=" ";if("product_import"===response.data.action){progress+=wc_square_admin_settings.i18n.skipped+": "+parseInt(response.data.skipped_products_count,10)+"<br/>";progress+=wc_square_admin_settings.i18n.updated+": "+parseInt(response.data.updated_products_count,10)+"<br/>";progress+=wc_square_admin_settings.i18n.imported+": "+parseInt(response.data.imported_products_count,10)}else if(response.data.percentage){progress+=parseInt(response.data.percentage,10)+"%"}$progress.html(progress);setTimeout(function(){getSyncStatus(response.data.id)},30*1000)}else{location.reload()}}else{$("#wc-square_clear-sync-records").prop("disabled",false);$("table.records .actions button").prop("disabled",false);$("table.sync .spinner").css("visibility","hidden");console.log(response)}}})};if(wc_square_admin_settings.existing_sync_job_id){getSyncStatus(wc_square_admin_settings.existing_sync_job_id)}$("#woocommerce_square_credit_card_enable_digital_wallets").on("change",function(){var wallet_settings=$(".wc-square-digital-wallet-options");if($("#woocommerce_square_credit_card_enable_digital_wallets").is(":checked")){wallet_settings.closest("tr").show()}else{wallet_settings.closest("tr").hide()}}).trigger("change")});
1
+ "use strict";jQuery(document).ready($=>{var pagenow=window.pagenow||"";if("woocommerce_page_wc-settings"!==pagenow){return}if(!wc_square_admin_settings.is_sandbox){$("#wc_square_sandbox_settings").hide();$("#wc_square_sandbox_settings").next().hide();$(".wc_square_sandbox_settings").closest("tr").hide()}$("#wc_square_system_of_record").on("change",e=>{var system_of_record=$(e.target).val();var $inventory_sync=$("#wc_square_enable_inventory_sync");var $inventory_sync_row=$inventory_sync.closest("tr");if("square"===system_of_record||"woocommerce"===system_of_record){$inventory_sync.next("span").html(wc_square_admin_settings.i18n.sync_inventory_label[system_of_record]);$inventory_sync_row.find(".description").html(wc_square_admin_settings.i18n.sync_inventory_description[system_of_record]);$inventory_sync_row.show()}else{$inventory_sync.prop("checked",false);$inventory_sync_row.hide()}if("square"===system_of_record){$("#wc_square_hide_missing_products").closest("tr").show()}else{$("#wc_square_hide_missing_products").closest("tr").hide()}}).trigger("change");$(".js-import-square-products").on("click",e=>{e.preventDefault();new $.WCBackboneModal.View({target:"wc-square-import-products"});$("#btn-close").on("click",e=>{e.preventDefault();$("button.modal-close").trigger("click")})});$("#wc-square-sync").on("click",e=>{e.preventDefault();new $.WCBackboneModal.View({target:"wc-square-sync"});$("#btn-close").on("click",e=>{e.preventDefault();$("button.modal-close").trigger("click")})});$(document.body).on("wc_backbone_modal_response",(e,target)=>{var data;switch(target){case"wc-square-import-products":$("#wpbody").block({message:null,overlayCSS:{opacity:"0.2"},onBlock:function onBlock(){$(".blockUI.blockOverlay").css({position:"fixed"})}});var update_during_import=$("#wc-square-import-product-updates").prop("checked");data={action:"wc_square_import_products_from_square",security:wc_square_admin_settings.import_products_from_square,update_during_import};$.post(wc_square_admin_settings.ajax_url,data,response=>{var message=response.data?response.data:null;if(message){alert(message)}location.reload()});break;case"wc-square-sync":$("table.sync").block({message:null,overlayCSS:{opacity:"0.2"}});$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});$("#wc-square_clear-sync-records").prop("disabled",true);data={action:"wc_square_sync_products_with_square",security:wc_square_admin_settings.sync_products_with_square};$.post(wc_square_admin_settings.ajax_url,data,response=>{if(response&&response.success){location.reload()}else{$("#wc-square_clear-sync-records").prop("disabled",false);$("table.sync").unblock();$("table.records").unblock()}});break;}});var noRecordsFoundRow="<tr><td colspan=\"4\"><em>"+wc_square_admin_settings.i18n.no_records_found+"</em></td></tr>";$("#wc-square_clear-sync-records").on("click",e=>{e.preventDefault();$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});var data={action:"wc_square_handle_sync_records",id:"all",handle:"delete",security:wc_square_admin_settings.handle_sync_with_square_records};$.post(wc_square_admin_settings.ajax_url,data,response=>{if(response&&response.success){$("table.records tbody").html(noRecordsFoundRow);$("#wc-square_clear-sync-records").prop("disabled",true)}else{if(response.data){alert(response.data)}console.log(response)}$("table.records").unblock()})});$(".records .actions button.action").on("click",e=>{e.preventDefault();$("table.records").block({message:null,overlayCSS:{opacity:"0.2"}});var recordId=$(e.currentTarget).data("id");var action=$(e.currentTarget).data("action");var data={action:"wc_square_handle_sync_records",id:recordId,handle:action,security:wc_square_admin_settings.handle_sync_with_square_records};$.post(wc_square_admin_settings.ajax_url,data,response=>{if(response&&response.success){var rowId="#record-"+recordId;if("delete"===action){$(rowId).remove();if(!$("table.records tbody tr").length){$("table.records tbody").html(noRecordsFoundRow);$("#wc-square_clear-sync-records").prop("disabled",true)}}else if("resolve"===action||"unsync"===action){$(rowId+" .type").html("<mark class=\"resolved\"><span>"+wc_square_admin_settings.i18n.resolved+"</span></mark>");$(rowId+" .actions").html("&mdash;")}}else{if(response&&response.data){alert(response.data)}console.log({record:recordId,action,response})}$("table.records").unblock()})});$("form").on("submit",e=>{var environment=$("#wc_square_enable_sandbox").is(":checked")?"sandbox":"production";$(e.target).append($("<input>",{type:"hidden",name:"wc_square_environment",value:environment}))});var getSyncStatus=job_id=>{var $progress=$("span.progress");if(!$progress||0===$progress.length){$("p.sync-result").append(" <span class=\"progress\" style=\"display:block\"></span>");$progress=$("span.progress")}var data={action:"wc_square_get_sync_with_square_status",security:wc_square_admin_settings.get_sync_with_square_status_nonce,job_id};$.post(wc_square_admin_settings.ajax_url,data,response=>{if(response&&response.data){if(response.success&&response.data.id){$("table.sync .spinner").css("visibility","visible");$("#wc-square_clear-sync-records").prop("disabled",true);$("table.records .actions button").prop("disabled",true);if("completed"!==response.data.status&&"failed"!==response.data.status){var progress=" ";if("product_import"===response.data.action){progress+=wc_square_admin_settings.i18n.skipped+": "+parseInt(response.data.skipped_products_count,10)+"<br/>";progress+=wc_square_admin_settings.i18n.updated+": "+parseInt(response.data.updated_products_count,10)+"<br/>";progress+=wc_square_admin_settings.i18n.imported+": "+parseInt(response.data.imported_products_count,10)}else if(response.data.percentage){progress+=parseInt(response.data.percentage,10)+"%"}$progress.html(progress);setTimeout(()=>{getSyncStatus(response.data.id)},30*1000)}else{location.reload()}}else{$("#wc-square_clear-sync-records").prop("disabled",false);$("table.records .actions button").prop("disabled",false);$("table.sync .spinner").css("visibility","hidden");console.log(response)}}})};if(wc_square_admin_settings.existing_sync_job_id){getSyncStatus(wc_square_admin_settings.existing_sync_job_id)}$("#woocommerce_square_credit_card_enable_digital_wallets").on("change",()=>{var wallet_settings=$(".wc-square-digital-wallet-options");if($("#woocommerce_square_credit_card_enable_digital_wallets").is(":checked")){wallet_settings.closest("tr").show()}else{wallet_settings.closest("tr").hide()}}).trigger("change")});
assets/js/admin/wc-square-payment-gateway-admin-order.min.js ADDED
@@ -0,0 +1 @@
 
1
+ "use strict";(function(){jQuery(document).ready(function($){"use strict";var accounting,ref,ref1,ref2,ref3,submitCapture,sv_wc_payment_gateway_admin_order,woocommerce_admin,woocommerce_admin_meta_boxes;sv_wc_payment_gateway_admin_order=(ref=window.sv_wc_payment_gateway_admin_order)!=null?ref:{};woocommerce_admin=(ref1=window.woocommerce_admin)!=null?ref1:{};woocommerce_admin_meta_boxes=(ref2=window.woocommerce_admin_meta_boxes)!=null?ref2:{};accounting=(ref3=window.accounting)!=null?ref3:{};$(".sv-wc-payment-gateway-partial-capture").appendTo("#woocommerce-order-items .inside");$("#woocommerce-order-items").on("click",".wc-square-payment-gateway-capture:not(.disabled)",function(e){e.preventDefault();if($(this).hasClass("partial-capture")){$("div.sv-wc-payment-gateway-partial-capture").slideDown();$("div.wc-order-data-row-toggle").not("div.sv-wc-payment-gateway-partial-capture").slideUp();return $("div.wc-order-totals-items").slideUp()}return submitCapture()});$(".sv-wc-payment-gateway-partial-capture").on("change keyup","#capture_amount",function(e){var total;total=accounting.unformat($(this).val(),woocommerce_admin.mon_decimal_point);if(total){$("button.capture-action").removeAttr("disabled")}else{$("button.capture-action").attr("disabled","disabled")}return $("button .capture-amount .amount").text(accounting.formatMoney(total,{symbol:woocommerce_admin_meta_boxes.currency_format_symbol,decimal:woocommerce_admin_meta_boxes.currency_format_decimal_sep,thousand:woocommerce_admin_meta_boxes.currency_format_thousand_sep,precision:woocommerce_admin_meta_boxes.currency_format_num_decimals,format:woocommerce_admin_meta_boxes.currency_format}))});$(".sv-wc-payment-gateway-partial-capture").on("click",".capture-action",function(e){var amount,comment;e.preventDefault();amount=$(".sv-wc-payment-gateway-partial-capture #capture_amount").val();comment=$(".sv-wc-payment-gateway-partial-capture #capture_comment").val();return submitCapture(amount,comment)});return submitCapture=function submitCapture(amount,comment){var data;if(amount==null){amount=""}if(comment==null){comment=""}if(confirm(sv_wc_payment_gateway_admin_order.capture_ays)){$("#woocommerce-order-items").block({message:null,overlayCSS:{background:"#fff",opacity:0.6}});data={action:sv_wc_payment_gateway_admin_order.capture_action,nonce:sv_wc_payment_gateway_admin_order.capture_nonce,gateway_id:sv_wc_payment_gateway_admin_order.gateway_id,order_id:sv_wc_payment_gateway_admin_order.order_id,amount,comment};return $.ajax({url:sv_wc_payment_gateway_admin_order.ajax_url,data}).done(function(response){if(response.data!=null&&response.data.message!=null){alert(response.data.message)}if(response.success){return location.reload()}}).fail(function(){return alert(sv_wc_payment_gateway_admin_order.capture_error)}).always(function(){return $("#woocommerce-order-items").unblock()})}}})}).call(void 0);
assets/js/admin/wc-square-payment-gateway-token-editor.min.js ADDED
@@ -0,0 +1 @@
 
1
+ "use strict";(function(){jQuery(document).ready(function($){"use strict";var handleError,ref,wc_payment_gateway_token_editor;wc_payment_gateway_token_editor=(ref=window.wc_payment_gateway_token_editor)!=null?ref:{};$(".sv_wc_payment_gateway_token_editor").each(function(){var tokens;tokens=$(this).find("tr.token");if(tokens.length===0){return $(this).find("tr.no-tokens").show()}return $(this).find("tr.no-tokens").hide()});$(".sv_wc_payment_gateway_token_editor").on("click",".button[data-action=\"remove\"]",function(e){var data,editor,row;e.preventDefault();if(!confirm(wc_payment_gateway_token_editor.actions.remove_token.ays)){return}editor=$(this).closest("table");editor.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}});editor.find(".error").remove();row=$(this).closest("tr");if(row.hasClass("new-token")){return row.remove()}data={action:"wc_payment_gateway_"+editor.data("gateway-id")+"_admin_remove_payment_token",user_id:$(this).data("user-id"),token_id:$(this).data("token-id"),security:wc_payment_gateway_token_editor.actions.remove_token.nonce};return $.post(wc_payment_gateway_token_editor.ajax_url,data).done(function(_this){return function(response){if(!response.success){return handleError(editor,response.data)}$(row).remove();if(editor.find("tr.token").length===0){return editor.find("tr.no-tokens").show()}}}(this)).fail(function(_this){return function(jqXHR,textStatus,error){return handleError(editor,textStatus+": "+error)}}(this)).always(function(_this){return function(){return editor.unblock()}}(this))});$("table.sv_wc_payment_gateway_token_editor").on("click",".button[data-action=\"add-new\"]",function(e){var body,count,data,editor;e.preventDefault();editor=$(this).closest("table");editor.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}});body=editor.find("tbody.tokens");count=body.find("tr.token").length;data={action:"wc_payment_gateway_"+editor.data("gateway-id")+"_admin_get_blank_payment_token",index:count+1,security:wc_payment_gateway_token_editor.actions.add_token.nonce};return $.post(wc_payment_gateway_token_editor.ajax_url,data,function(response){if(response.success===true){body.append(response.data)}editor.find("tr.no-tokens").hide();return editor.unblock()})});$("table.sv_wc_payment_gateway_token_editor").on("click",".button[data-action=\"refresh\"]",function(e){var body,count,data,editor;e.preventDefault();editor=$(this).closest("table");editor.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}});editor.find(".error").remove();body=editor.find("tbody.tokens");count=body.find("tr.token").length;data={action:"wc_payment_gateway_"+editor.data("gateway-id")+"_admin_refresh_payment_tokens",user_id:$(this).data("user-id"),security:wc_payment_gateway_token_editor.actions.refresh.nonce};return $.post(wc_payment_gateway_token_editor.ajax_url,data).done(function(_this){return function(response){if(!response.success){return handleError(editor,response.data)}if(response.data!=null){editor.find("tr.no-tokens").hide();return body.html(response.data)}body.empty();return editor.find("tr.no-tokens").show()}}(this)).fail(function(_this){return function(jqXHR,textStatus,error){return handleError(editor,textStatus+": "+error)}}(this)).always(function(_this){return function(){return editor.unblock()}}(this))});$("table.sv_wc_payment_gateway_token_editor").on("click",".sv-wc-payment-gateway-token-editor-action-button[data-action=\"save\"]",function(e){var actions_row,editor,focused,inputs;editor=$(this).closest("table");actions_row=editor.find("tfoot th");editor.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}});actions_row.find(".error, .success").remove();inputs=editor.find("tbody.tokens tr.token input[type=\"text\"]");focused=false;return inputs.each(function(index){var pattern,required,value;$(this).removeClass("error");value=$(this).val();required=$(this).prop("required");pattern=$(this).attr("pattern");if(!(required||value)){return}if(!value.match(pattern)||required&&!value){e.preventDefault();$(this).addClass("error");if(!focused){actions_row.prepend("<span class=\"error\">"+wc_payment_gateway_token_editor.actions.save.error+"</span>");$(this).focus();focused=true}return editor.unblock()}})});return handleError=function handleError(editor,error,message){if(message==null){message=""}console.error(error);if(!message){message=wc_payment_gateway_token_editor.i18n.general_error}return editor.find("th.actions").prepend("<span class=\"error\">"+message+"</span>")}})}).call(void 0);
assets/js/frontend/wc-square-digital-wallet.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);Object.defineProperty(Constructor,"prototype",{writable:false});return Constructor}jQuery(document).ready(function($){var WC_Square_Digital_Wallet_Handler=function(){function WC_Square_Digital_Wallet_Handler(args){_classCallCheck(this,WC_Square_Digital_Wallet_Handler);this.args=args;this.payment_request=args.payment_request;this.total_amount=args.payment_request.total.amount;this.wallet="#wc-square-digital-wallet";this.buttons=".wc-square-wallet-buttons";if($(this.wallet).length===0){return}$(this.wallet).hide();$(this.buttons).hide();this.build_digital_wallet();this.attach_page_events()}_createClass(WC_Square_Digital_Wallet_Handler,[{key:"build_digital_wallet",value:function build_digital_wallet(){var _this=this;this.block_ui();this.get_payment_request().then(function(response){_this.payment_request=JSON.parse(response);_this.total_amount=_this.payment_request.total.amount;_this.load_square_form();_this.unblock_ui()},function(message){_this.log("[Square] Could not build payment request. "+message,"error");$(_this.wallet).hide()})}},{key:"attach_page_events",value:function attach_page_events(){var _this2=this;if(this.args.context==="product"){var addToCartButton=$(".single_add_to_cart_button");$("#wc-square-apple-pay, #wc-square-google-pay").on("click",function(e){if(addToCartButton.is(".disabled")){e.stopImmediatePropagation();if(addToCartButton.is(".wc-variation-is-unavailable")){window.alert(wc_add_to_cart_variation_params.i18n_unavailable_text)}else if(addToCartButton.is(".wc-variation-selection-needed")){window.alert(wc_add_to_cart_variation_params.i18n_make_a_selection_text)}return}_this2.add_to_cart()});$(document.body).on("woocommerce_variation_has_changed",function(){return _this2.build_digital_wallet()});$(".quantity").on("input",".qty",function(){return _this2.build_digital_wallet()})}if(this.args.context==="cart"){$(document.body).on("updated_cart_totals",function(){return _this2.build_digital_wallet()})}if(this.args.context==="checkout"){$(document.body).on("updated_checkout",function(){return _this2.build_digital_wallet()})}}},{key:"load_square_form",value:function load_square_form(){if(this.payment_form){this.log("[Square] Destroying digital wallet payment form");this.payment_form.destroy()}this.log("[Square] Building digital wallet payment form");this.payment_form=new SqPaymentForm(this.get_form_params());this.payment_form.build()}},{key:"get_form_params",value:function get_form_params(){var _this3=this;var params={applicationId:this.args.application_id,locationId:this.args.location_id,autobuild:false,applePay:{elementId:"wc-square-apple-pay"},googlePay:{elementId:"wc-square-google-pay"},callbacks:{paymentFormLoaded:function paymentFormLoaded(){return _this3.unblock_ui()},createPaymentRequest:function createPaymentRequest(){return _this3.create_payment_request()},methodsSupported:function methodsSupported(methods,unsupportedReason){return _this3.methods_supported(methods,unsupportedReason)},shippingContactChanged:function shippingContactChanged(shippingContact,done){return _this3.handle_shipping_address_changed(shippingContact,done)},shippingOptionChanged:function shippingOptionChanged(shippingOption,done){return _this3.handle_shipping_option_changed(shippingOption,done)},cardNonceResponseReceived:function cardNonceResponseReceived(errors,nonce,cardData,billingContact,shippingContact,shippingOption){_this3.handle_card_nonce_response(errors,nonce,cardData,billingContact,shippingContact,shippingOption)}}};if(this.payment_request.requestShippingAddress===false){delete params.callbacks.shippingOptionChanged}if(this.args.hide_button_options.includes("google")){delete params.googlePay}if(this.args.hide_button_options.includes("apple")){delete params.applePay}return params}},{key:"create_payment_request",value:function create_payment_request(){return this.payment_request}},{key:"methods_supported",value:function methods_supported(methods,unsupportedReason){if(methods.applePay===true||methods.googlePay===true){if(methods.applePay===true){$("#wc-square-apple-pay").show()}if(methods.googlePay===true){$("#wc-square-google-pay").show()}$(this.wallet).show()}else{this.log(unsupportedReason)}}},{key:"get_payment_request",value:function get_payment_request(){var _this4=this;return new Promise(function(resolve,reject){var data={context:_this4.args.context,security:_this4.args.payment_request_nonce};if(_this4.args.context==="product"){var product_data=_this4.get_product_data();$.extend(data,product_data)}$.post(_this4.get_ajax_url("get_payment_request"),data,function(response){if(response.success){return resolve(response.data)}return reject(response.data)})})}},{key:"handle_shipping_address_changed",value:function handle_shipping_address_changed(shippingContact,done){var data={context:this.args.context,shipping_contact:shippingContact.data,security:this.args.recalculate_totals_nonce};this.recalculate_totals(data).then(function(response){return done(response)},function(){return done({error:"Bad Request"})})}},{key:"handle_shipping_option_changed",value:function handle_shipping_option_changed(shippingOption,done){var data={context:this.args.context,shipping_option:shippingOption.data.id,security:this.args.recalculate_totals_nonce};this.recalculate_totals(data).then(function(response){return done(response)},function(){return done({error:"Bad Request"})})}},{key:"handle_card_nonce_response",value:function handle_card_nonce_response(errors,nonce,cardData,billingContact,shippingContact,shippingOption){if(errors){return this.render_errors(errors)}if(!nonce){return this.render_errors(this.args.general_error)}this.block_ui();var data={action:"",_wpnonce:this.args.process_checkout_nonce,billing_first_name:billingContact.givenName?billingContact.givenName:"",billing_last_name:billingContact.familyName?billingContact.familyName:"",billing_company:"",billing_email:shippingContact.email?shippingContact.email:"",billing_phone:shippingContact.phone?shippingContact.phone:"",billing_country:billingContact.country?billingContact.country.toUpperCase():"",billing_address_1:billingContact.addressLines&&billingContact.addressLines[0]?billingContact.addressLines[0]:"",billing_address_2:billingContact.addressLines&&billingContact.addressLines[1]?billingContact.addressLines[1]:"",billing_city:billingContact.city?billingContact.city:"",billing_state:billingContact.region?billingContact.region:"",billing_postcode:billingContact.postalCode?billingContact.postalCode:"",shipping_first_name:shippingContact.givenName?shippingContact.givenName:"",shipping_last_name:shippingContact.familyName?shippingContact.familyName:"",shipping_company:"",shipping_country:shippingContact.country?shippingContact.country.toUpperCase():"",shipping_address_1:shippingContact.addressLines&&shippingContact.addressLines[0]?shippingContact.addressLines[0]:"",shipping_address_2:shippingContact.addressLines&&shippingContact.addressLines[1]?shippingContact.addressLines[1]:"",shipping_city:shippingContact.city?shippingContact.city:"",shipping_state:shippingContact.region?shippingContact.region:"",shipping_postcode:shippingContact.postalCode?shippingContact.postalCode:"",shipping_method:[!shippingOption?null:shippingOption.id],order_comments:"",payment_method:"square_credit_card",ship_to_different_address:1,terms:1,"wc-square-credit-card-payment-nonce":nonce,"wc-square-credit-card-last-four":cardData.last_4?cardData.last_4:null,"wc-square-credit-card-exp-month":cardData.exp_month?cardData.exp_month:null,"wc-square-credit-card-exp-year":cardData.exp_year?cardData.exp_year:null,"wc-square-credit-card-payment-postcode":cardData.billing_postal_code?cardData.billing_postal_code:null,"wc-square-digital-wallet-type":cardData.digital_wallet_type};if(cardData.digital_wallet_type==="GOOGLE_PAY"){if(billingContact.givenName){data.billing_first_name=billingContact.givenName.split(" ").slice(0,1).join(" ");data.billing_last_name=billingContact.givenName.split(" ").slice(1).join(" ")}if(shippingContact.givenName){data.shipping_last_name=shippingContact.givenName.split(" ").slice(0,1).join(" ");data.shipping_last_name=shippingContact.givenName.split(" ").slice(1).join(" ")}}if(!data.billing_phone&&billingContact.phone){data.billing_phone=billingContact.phone}if(this.args.is_3d_secure_enabled){this.log("3DS verification enabled. Verifying buyer");var self=this;this.payment_form.verifyBuyer(nonce,self.get_verification_details(billingContact,shippingContact),function(err,verificationResult){if(err==null){self.log("3DS verification successful");data["wc-square-credit-card-buyer-verification-token"]=verificationResult.token;self.do_checkout(data)}else{self.log("3DS verification failed");self.log(err);self.render_errors([err.message])}})}else{this.do_checkout(data)}}},{key:"do_checkout",value:function do_checkout(data){var _this5=this;this.process_digital_wallet_checkout(data).then(function(response){window.location=response.redirect},function(response){_this5.log(response,"error");_this5.render_errors_html(response.messages)})}},{key:"get_verification_details",value:function get_verification_details(billingContact,shippingContact){var verification_details={intent:"CHARGE",amount:this.total_amount,currencyCode:this.payment_request.currencyCode,billingContact:{familyName:billingContact.familyName?billingContact.familyName:"",givenName:billingContact.givenName?billingContact.givenName:"",email:shippingContact.email?shippingContact.email:"",country:billingContact.country?billingContact.country.toUpperCase():"",region:billingContact.region?billingContact.region:"",city:billingContact.city?billingContact.city:"",postalCode:billingContact.postalCode?billingContact.postalCode:"",phone:shippingContact.phone?shippingContact.phone:"",addressLines:billingContact.addressLines?billingContact.addressLines:""}};this.log(verification_details);return verification_details}},{key:"recalculate_totals",value:function recalculate_totals(data){var _this6=this;return new Promise(function(resolve,reject){return $.post(_this6.get_ajax_url("recalculate_totals"),data,function(response){if(response.success){_this6.total_amount=response.data.total.amount;return resolve(response.data)}return reject(response.data)})})}},{key:"get_product_data",value:function get_product_data(){var product_id=$(".single_add_to_cart_button").val();var attributes={};if($(".single_variation_wrap").length){product_id=$(".single_variation_wrap").find("input[name=\"product_id\"]").val();if($(".variations_form").length){$(".variations_form").find(".variations select").each(function(index,select){var attribute_name=$(select).data("attribute_name")||$(select).attr("name");var value=$(select).val()||"";return attributes[attribute_name]=value})}}return{product_id:product_id,quantity:$(".quantity .qty").val(),attributes:attributes}}},{key:"add_to_cart",value:function add_to_cart(){var _this7=this;var data={security:this.args.add_to_cart_nonce};var product_data=this.get_product_data();$.extend(data,product_data);$.post(this.get_ajax_url("add_to_cart"),data,function(response){if(response.error){return window.alert(response.data)}var data=JSON.parse(response.data);_this7.payment_request=data.payment_request;_this7.args.payment_request_nonce=data.payment_request_nonce;_this7.args.add_to_cart_nonce=data.add_to_cart_nonce;_this7.args.recalculate_totals_nonce=data.recalculate_totals_nonce;_this7.args.process_checkout_nonce=data.process_checkout_nonce})}},{key:"process_digital_wallet_checkout",value:function process_digital_wallet_checkout(data){var _this8=this;return new Promise(function(resolve,reject){$.post(_this8.get_ajax_url("process_checkout"),data,function(response){if(response.result==="success"){return resolve(response)}return reject(response)})})}},{key:"get_ajax_url",value:function get_ajax_url(request){return this.args.ajax_url.replace("%%endpoint%%","square_digital_wallet_"+request)}},{key:"render_errors_html",value:function render_errors_html(errors_html){$(".woocommerce-error, .woocommerce-message").remove();var element=this.args.context==="product"?$(".product"):$(".shop_table.cart").closest("form");element.before(errors_html);this.unblock_ui();$("html, body").animate({scrollTop:element.offset().top-100},1000)}},{key:"render_errors",value:function render_errors(errors){var error_message_html="<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>";this.render_errors_html(error_message_html)}},{key:"block_ui",value:function block_ui(){$(this.buttons).block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})}},{key:"unblock_ui",value:function unblock_ui(){$(this.buttons).unblock()}},{key:"log",value:function log(message){var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"notice";if(!this.args.logging_enabled){return}if(type==="error"){return console.error(message)}return console.log(message)}}]);return WC_Square_Digital_Wallet_Handler}();window.WC_Square_Digital_Wallet_Handler=WC_Square_Digital_Wallet_Handler});
1
+ "use strict";function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);enumerableOnly&&(symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable})),keys.push.apply(keys,symbols)}return keys}function _objectSpread(target){for(var i=1;i<arguments.length;i++){var source=null!=arguments[i]?arguments[i]:{};i%2?ownKeys(Object(source),!0).forEach(function(key){_defineProperty(target,key,source[key])}):Object.getOwnPropertyDescriptors?Object.defineProperties(target,Object.getOwnPropertyDescriptors(source)):ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}return target}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}jQuery(document).ready($=>{class WC_Square_Digital_Wallet_Handler{constructor(args){this.args=args;this.payment_request=args.payment_request;this.total_amount=args.payment_request.total.amount;this.cartForm=".cart";this.wallet="#wc-square-digital-wallet";this.buttons=".wc-square-wallet-buttons";this.isGooglePayHidden=this.args.hide_button_options.includes("google");this.isApplePayHidden=this.args.hide_button_options.includes("apple");if($(this.wallet).length===0){return}$(this.wallet).hide();$(this.buttons).hide();this.build_digital_wallet();this.attach_page_events();this.buildDigitalWalletDebounced=this.debounce(this.build_digital_wallet,500)}build_digital_wallet(){this.block_ui();this.get_payment_request().then(response=>{this.payment_request=JSON.parse(response);this.total_amount=this.payment_request.total.amount;this.load_square_form()},message=>{this.log("[Square] Could not build payment request. "+message,"error");$(this.wallet).hide()})}attach_page_events(){if(this.args.context==="product"){var addToCartButton=$(".single_add_to_cart_button");$("#apple-pay-button, #wc-square-google-pay").on("click",e=>{if(addToCartButton.is(".disabled")){e.stopImmediatePropagation();if(addToCartButton.is(".wc-variation-is-unavailable")){window.alert(wc_add_to_cart_variation_params.i18n_unavailable_text)}else if(addToCartButton.is(".wc-variation-selection-needed")){window.alert(wc_add_to_cart_variation_params.i18n_make_a_selection_text)}return}this.add_to_cart()});$(document.body).on("woocommerce_variation_has_changed",()=>this.build_digital_wallet());$(".quantity").on("input",".qty",()=>this.build_digital_wallet())}if(this.args.context==="cart"){$(document.body).on("updated_cart_totals",()=>this.build_digital_wallet())}if(this.args.context==="checkout"){$(document.body).on("updated_checkout",()=>this.build_digital_wallet())}}load_square_form(){if(this.googlePay){this.googlePay.destroy();this.squareFormLoaded=false}if(this.applePay){this.applePay.destroy();this.squareFormLoaded=false}if(this.squareFormLoaded){return}this.squareFormLoaded=true;this.log("[Square] Building digital wallet payment form");var{applicationId,locationId}=this.get_form_params();this.payments=window.Square.payments(applicationId,locationId);this.initializeDigitalWalletPaymentMethods()}initializeDigitalWalletPaymentMethods(){var _this=this;return _asyncToGenerator(function*(){if(!_this.payments){return}var paymentRequest=_this.payments.paymentRequest(_this.create_payment_request());_this.registerDigitalWalletShippingEventHandlers(paymentRequest);if(!_this.isGooglePayHidden){_this.googlePay=yield _this.payments.googlePay(paymentRequest);_this.googlePay.attach("#wc-square-google-pay",{buttonSizeMode:"fill",buttonType:"long",buttonColor:_this.args.google_pay_color});$("#wc-square-google-pay").on("click",function(){var _ref=_asyncToGenerator(function*(e){return _this.handleGooglePayPaymentMethodSubmission(e,_this.googlePay)});return function(_x){return _ref.apply(this,arguments)}}());$("#wc-square-google-pay").show()}if(!_this.isApplePayHidden){try{_this.applePay=yield _this.payments.applePay(paymentRequest);$("#apple-pay-button").on("click",function(){var _ref2=_asyncToGenerator(function*(e){return _this.handleApplePayPaymentMethodSubmission(e,_this.applePay)});return function(_x2){return _ref2.apply(this,arguments)}}());$("#apple-pay-button").show()}catch(e){console.log(e.message)}}if(_this.googlePay||_this.applePay){$(_this.wallet).show();_this.unblock_ui()}})()}handleGooglePayPaymentMethodSubmission(e){var _arguments=arguments,_this2=this;return _asyncToGenerator(function*(){var googlePay=_arguments.length>1&&_arguments[1]!==undefined?_arguments[1]:null;e.preventDefault();if(!googlePay){return}var result=yield googlePay.tokenize();if(result.status==="OK"){var cardData=_objectSpread(_objectSpread({},result.details.card),{},{digital_wallet_type:result.details.method});var billingAndShippingData={billingContact:result.details.billing};if(result.details.shipping){billingAndShippingData.shippingContact=result.details.shipping.contact;billingAndShippingData.shippingOption=result.details.shipping.option}_this2.handle_card_nonce_response(false,result.token,cardData,billingAndShippingData)}})()}handleApplePayPaymentMethodSubmission(e){var _arguments2=arguments,_this3=this;return _asyncToGenerator(function*(){var applePay=_arguments2.length>1&&_arguments2[1]!==undefined?_arguments2[1]:null;e.preventDefault();if(!applePay){return}var result=yield applePay.tokenize();if(result.status==="OK"){var cardData=_objectSpread(_objectSpread({},result.details.card),{},{digital_wallet_type:result.details.method});var billingAndShippingData={billingContact:result.details.billing};if(result.details.shipping){billingAndShippingData.shippingContact=result.details.shipping.contact;billingAndShippingData.shippingOption=result.details.shipping.option}_this3.handle_card_nonce_response(false,result.token,cardData,billingAndShippingData)}})()}registerDigitalWalletShippingEventHandlers(paymentRequest){paymentRequest.addEventListener("shippingoptionchanged",option=>this.handle_shipping_option_changed(option));paymentRequest.addEventListener("shippingcontactchanged",shippingContact=>this.handle_shipping_address_changed(shippingContact))}get_form_params(){var params={applicationId:this.args.application_id,locationId:this.args.location_id,autobuild:false,applePay:{elementId:"apple-pay-button"},googlePay:{elementId:"wc-square-google-pay"}};if(this.payment_request.requestShippingAddress===false){delete params.callbacks.shippingOptionChanged}if(this.args.hide_button_options.includes("google")){delete params.googlePay}if(this.args.hide_button_options.includes("apple")){delete params.applePay}return params}create_payment_request(){return this.payment_request}methods_supported(methods,unsupportedReason){if(methods.applePay===true||methods.googlePay===true){if(methods.applePay===true){$("#apple-pay-button").show()}if(methods.googlePay===true){$("#wc-square-google-pay").show()}$(this.wallet).show()}else{this.log(unsupportedReason)}}get_payment_request(){return new Promise((resolve,reject)=>{var data={context:this.args.context,security:this.args.payment_request_nonce};if(this.args.context==="product"){var product_data=this.get_product_data();$.extend(data,product_data)}$.post(this.get_ajax_url("get_payment_request"),data,response=>{if(response.success){return resolve(response.data)}return reject(response.data)})})}handle_shipping_address_changed(shippingContact){var _this4=this;return _asyncToGenerator(function*(){var data={context:_this4.args.context,shipping_contact:shippingContact,security:_this4.args.recalculate_totals_nonce};var response=yield _this4.recalculate_totals(data);return response})()}handle_shipping_option_changed(shippingOption){var _this5=this;return _asyncToGenerator(function*(){var data={context:_this5.args.context,shipping_option:shippingOption.id,security:_this5.args.recalculate_totals_nonce};var response=yield _this5.recalculate_totals(data);return response})()}handle_card_nonce_response(){var errors=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;var nonce=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var cardData=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var billingAndShippingData=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};if(errors){return this.render_errors(errors)}if(!nonce){return this.render_errors(this.args.general_error)}this.block_ui();var{billingContact={},shippingContact={},shippingOption=null}=billingAndShippingData;var data={action:"",_wpnonce:this.args.process_checkout_nonce,billing_first_name:billingContact.givenName?billingContact.givenName:"",billing_last_name:billingContact.familyName?billingContact.familyName:"",billing_company:"",billing_email:shippingContact.email?shippingContact.email:billingContact.email?billingContact.email:"",billing_phone:shippingContact.phone?shippingContact.phone:"",billing_country:billingContact.countryCode?billingContact.countryCode.toUpperCase():"",billing_address_1:billingContact.addressLines&&billingContact.addressLines[0]?billingContact.addressLines[0]:"",billing_address_2:billingContact.addressLines&&billingContact.addressLines[1]?billingContact.addressLines[1]:"",billing_city:billingContact.city?billingContact.city:"",billing_state:billingContact.state?billingContact.state:"",billing_postcode:billingContact.postalCode?billingContact.postalCode:"",shipping_first_name:shippingContact.givenName?shippingContact.givenName:"",shipping_last_name:shippingContact.familyName?shippingContact.familyName:"",shipping_company:"",shipping_country:shippingContact.countryCode?shippingContact.countryCode.toUpperCase():"",shipping_address_1:shippingContact.addressLines&&shippingContact.addressLines[0]?shippingContact.addressLines[0]:"",shipping_address_2:shippingContact.addressLines&&shippingContact.addressLines[1]?shippingContact.addressLines[1]:"",shipping_city:shippingContact.city?shippingContact.city:"",shipping_state:shippingContact.state?shippingContact.state:"",shipping_postcode:shippingContact.postalCode?shippingContact.postalCode:"",shipping_method:[!shippingOption?null:shippingOption.id],order_comments:"",payment_method:"square_credit_card",ship_to_different_address:1,terms:1,"wc-square-credit-card-payment-nonce":nonce,"wc-square-credit-card-last-four":cardData.last4?cardData.last4:null,"wc-square-credit-card-exp-month":cardData.expMonth?cardData.expMonth:null,"wc-square-credit-card-exp-year":cardData.expYear?cardData.expYear:null,"wc-square-credit-card-payment-postcode":cardData.billing.postalCode?cardData.billing.postalCode:null,"wc-square-digital-wallet-type":cardData.digital_wallet_type};if(cardData.digital_wallet_type==="GOOGLE_PAY"){if(billingContact.givenName){data.billing_first_name=billingContact.givenName.split(" ").slice(0,1).join(" ");data.billing_last_name=billingContact.givenName.split(" ").slice(1).join(" ")}if(shippingContact.givenName){data.shipping_last_name=shippingContact.givenName.split(" ").slice(0,1).join(" ");data.shipping_last_name=shippingContact.givenName.split(" ").slice(1).join(" ")}}if(!data.billing_phone&&billingContact.phone){data.billing_phone=billingContact.phone}if(this.args.is_3d_secure_enabled){this.log("3DS verification enabled. Verifying buyer");var self=this;try{this.payments.verifyBuyer(nonce,self.get_verification_details(billingContact,shippingContact)).then(verificationResult=>{if(verificationResult.token){self.log("3DS verification successful");data["wc-square-credit-card-buyer-verification-token"]=verificationResult.token;self.do_checkout(data)}})}catch(err){self.log("3DS verification failed");self.log(err);self.render_errors([err.message])}}else{this.do_checkout(data)}}do_checkout(data){this.process_digital_wallet_checkout(data).then(response=>{window.location=response.redirect},response=>{this.log(response,"error");this.render_errors_html(response.messages)})}get_verification_details(billingContact,shippingContact){var verification_details={intent:"CHARGE",amount:this.total_amount,currencyCode:this.payment_request.currencyCode,billingContact:{familyName:billingContact.familyName?billingContact.familyName:"",givenName:billingContact.givenName?billingContact.givenName:"",email:shippingContact.email?shippingContact.email:"",countryCode:billingContact.countryCode?billingContact.countryCode.toUpperCase():"",state:billingContact.state?billingContact.state:"",city:billingContact.city?billingContact.city:"",postalCode:billingContact.postalCode?billingContact.postalCode:"",phone:shippingContact.phone?shippingContact.phone:"",addressLines:billingContact.addressLines?billingContact.addressLines:""}};this.log(verification_details);return verification_details}recalculate_totals(data){var _this6=this;return _asyncToGenerator(function*(){return new Promise((resolve,reject)=>{return $.post(_this6.get_ajax_url("recalculate_totals"),data,response=>{if(response.success){_this6.total_amount=response.data.total.amount;return resolve(response.data)}return reject(response.data)})})})()}get_product_data(){var product_id=$(".single_add_to_cart_button").val();var attributes={};if($(".single_variation_wrap").length){product_id=$(".single_variation_wrap").find("input[name=\"product_id\"]").val();if($(".variations_form").length){$(".variations_form").find(".variations select").each((index,select)=>{var attribute_name=$(select).data("attribute_name")||$(select).attr("name");var value=$(select).val()||"";return attributes[attribute_name]=value})}}return{product_id,quantity:$(".quantity .qty").val(),attributes}}add_to_cart(){var data={security:this.args.add_to_cart_nonce};var product_data=this.get_product_data();$.extend(data,product_data);$.post(this.get_ajax_url("add_to_cart"),data,response=>{if(response.error){return window.alert(response.data)}var data=JSON.parse(response.data);this.payment_request=data.payment_request;this.args.payment_request_nonce=data.payment_request_nonce;this.args.add_to_cart_nonce=data.add_to_cart_nonce;this.args.recalculate_totals_nonce=data.recalculate_totals_nonce;this.args.process_checkout_nonce=data.process_checkout_nonce})}process_digital_wallet_checkout(data){return new Promise((resolve,reject)=>{$.post(this.get_ajax_url("process_checkout"),data,response=>{if(response.result==="success"){return resolve(response)}return reject(response)})})}get_ajax_url(request){return this.args.ajax_url.replace("%%endpoint%%","square_digital_wallet_"+request)}render_errors_html(errors_html){$(".woocommerce-error, .woocommerce-message").remove();var element=this.args.context==="product"?$(".product"):$(".shop_table.cart").closest("form");element.before(errors_html);this.unblock_ui();$("html, body").animate({scrollTop:element.offset().top-100},1000)}render_errors(errors){var error_message_html="<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>";this.render_errors_html(error_message_html)}block_ui(){$(this.buttons).block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})}unblock_ui(){$(this.buttons).unblock()}log(message){var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"notice";if(!this.args.logging_enabled){return}if(type==="error"){return console.error(message)}return console.log(message)}debounce(func,wait,immediate){var timeout;return function(){var context=this,args=arguments;var later=function later(){timeout=null;if(!immediate)func.apply(context,args)};var callNow=immediate&&!timeout;clearTimeout(timeout);timeout=setTimeout(later,wait);if(callNow)func.apply(context,args)}}}window.WC_Square_Digital_Wallet_Handler=WC_Square_Digital_Wallet_Handler});
assets/js/frontend/wc-square-payment-gateway-apple-pay.min.js ADDED
@@ -0,0 +1 @@
 
1
+ "use strict";(function(){var bind=function bind(fn,me){return function(){return fn.apply(me,arguments)}},extend=function extend(child,parent){for(var key in parent){if(hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child},hasProp={}.hasOwnProperty;jQuery(document).ready(function($){"use strict";window.SV_WC_Apple_Pay_Handler=function(){function SV_WC_Apple_Pay_Handler(args){this.get_payment_request=bind(this.get_payment_request,this);this.reset_payment_request=bind(this.reset_payment_request,this);this.attach_update_events=bind(this.attach_update_events,this);this.on_cancel_payment=bind(this.on_cancel_payment,this);this.process_authorization=bind(this.process_authorization,this);this.on_payment_authorized=bind(this.on_payment_authorized,this);this.on_shipping_method_selected=bind(this.on_shipping_method_selected,this);this.on_shipping_contact_selected=bind(this.on_shipping_contact_selected,this);this.on_payment_method_selected=bind(this.on_payment_method_selected,this);this.validate_merchant=bind(this.validate_merchant,this);this.on_validate_merchant=bind(this.on_validate_merchant,this);this.params=sv_wc_apple_pay_params;this.payment_request=args.payment_request;this.buttons=".sv-wc-apple-pay-button";if(this.is_available()){if(this.payment_request){$(this.buttons).show()}this.init();this.attach_update_events()}}SV_WC_Apple_Pay_Handler.prototype.is_available=function(){if(!window.ApplePaySession){return false}return ApplePaySession.canMakePaymentsWithActiveCard(this.params.merchant_id).then(function(_this){return function(canMakePayments){return canMakePayments}}(this))};SV_WC_Apple_Pay_Handler.prototype.init=function(){return $(document.body).on("click",".sv-wc-apple-pay-button",function(_this){return function(e){var error;e.preventDefault();_this.block_ui();try{_this.session=new ApplePaySession(1,_this.payment_request);_this.session.onvalidatemerchant=function(event){return _this.on_validate_merchant(event)};_this.session.onpaymentmethodselected=function(event){return _this.on_payment_method_selected(event)};_this.session.onshippingcontactselected=function(event){return _this.on_shipping_contact_selected(event)};_this.session.onshippingmethodselected=function(event){return _this.on_shipping_method_selected(event)};_this.session.onpaymentauthorized=function(event){return _this.on_payment_authorized(event)};_this.session.oncancel=function(event){return _this.on_cancel_payment(event)};return _this.session.begin()}catch(_error){error=_error;return _this.fail_payment(error)}}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_validate_merchant=function(event){return this.validate_merchant(event.validationURL).then(function(_this){return function(merchant_session){merchant_session=$.parseJSON(merchant_session);return _this.session.completeMerchantValidation(merchant_session)}}(this),function(_this){return function(response){_this.session.abort();return _this.fail_payment("Merchant could no be validated. "+response.message)}}(this))};SV_WC_Apple_Pay_Handler.prototype.validate_merchant=function(url){return new Promise(function(_this){return function(resolve,reject){var data;data={action:"sv_wc_apple_pay_validate_merchant",nonce:_this.params.validate_nonce,merchant_id:_this.params.merchant_id,url};return $.post(_this.params.ajax_url,data,function(response){if(response.success){return resolve(response.data)}return reject(response.data)})}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_payment_method_selected=function(event){return new Promise(function(_this){return function(resolve,reject){var data;data={action:"sv_wc_apple_pay_recalculate_totals",nonce:_this.params.recalculate_totals_nonce};return $.post(_this.params.ajax_url,data,function(response){if(response.success){data=response.data;return resolve(_this.session.completePaymentMethodSelection(data.total,data.line_items))}console.error("[Apple Pay] Error selecting a shipping contact. "+response.data.message);return reject(_this.session.completePaymentMethodSelection(_this.payment_request.total,_this.payment_request.lineItems))})}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_shipping_contact_selected=function(event){return new Promise(function(_this){return function(resolve,reject){var data;data={action:"sv_wc_apple_pay_recalculate_totals",nonce:_this.params.recalculate_totals_nonce,contact:event.shippingContact};return $.post(_this.params.ajax_url,data,function(response){if(response.success){data=response.data;return resolve(_this.session.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS,data.shipping_methods,data.total,data.line_items))}console.error("[Apple Pay] Error selecting a shipping contact. "+response.data.message);return reject(_this.session.completeShippingContactSelection(ApplePaySession.STATUS_FAILURE,[],_this.payment_request.total,_this.payment_request.lineItems))})}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_shipping_method_selected=function(event){return new Promise(function(_this){return function(resolve,reject){var data;data={action:"sv_wc_apple_pay_recalculate_totals",nonce:_this.params.recalculate_totals_nonce,method:event.shippingMethod.identifier};return $.post(_this.params.ajax_url,data,function(response){if(response.success){data=response.data;return resolve(_this.session.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS,data.total,data.line_items))}console.error("[Apple Pay] Error selecting a shipping method. "+response.data.message);return reject(_this.session.completeShippingMethodSelection(ApplePaySession.STATUS_FAILURE,_this.payment_request.total,_this.payment_request.lineItems))})}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_payment_authorized=function(event){return this.process_authorization(event.payment).then(function(_this){return function(response){_this.set_payment_status(true);return _this.complete_purchase(response)}}(this),function(_this){return function(response){_this.set_payment_status(false);return _this.fail_payment("Payment could no be processed. "+response.message)}}(this))};SV_WC_Apple_Pay_Handler.prototype.process_authorization=function(payment){return new Promise(function(_this){return function(resolve,reject){var data;data={action:"sv_wc_apple_pay_process_payment",nonce:_this.params.process_nonce,type:_this.type,payment:JSON.stringify(payment)};return $.post(_this.params.ajax_url,data,function(response){if(response.success){return resolve(response.data)}return reject(response.data)})}}(this))};SV_WC_Apple_Pay_Handler.prototype.on_cancel_payment=function(event){return this.unblock_ui()};SV_WC_Apple_Pay_Handler.prototype.complete_purchase=function(response){return window.location=response.redirect};SV_WC_Apple_Pay_Handler.prototype.fail_payment=function(error){console.error("[Apple Pay] "+error);this.unblock_ui();return this.render_errors([this.params.generic_error])};SV_WC_Apple_Pay_Handler.prototype.set_payment_status=function(success){var status;if(success){status=ApplePaySession.STATUS_SUCCESS}else{status=ApplePaySession.STATUS_FAILURE}return this.session.completePayment(status)};SV_WC_Apple_Pay_Handler.prototype.attach_update_events=function(){};SV_WC_Apple_Pay_Handler.prototype.reset_payment_request=function(data){if(data==null){data={}}this.block_ui();return this.get_payment_request(data).then(function(_this){return function(response){$(_this.buttons).show();_this.payment_request=$.parseJSON(response);return _this.unblock_ui()}}(this),function(_this){return function(response){console.error("[Apple Pay] Could not build payment request. "+response.message);$(_this.buttons).hide();return _this.unblock_ui()}}(this))};SV_WC_Apple_Pay_Handler.prototype.get_payment_request=function(data){return new Promise(function(_this){return function(resolve,reject){var base_data;base_data={action:"sv_wc_apple_pay_get_payment_request",type:_this.type};$.extend(data,base_data);return $.post(_this.params.ajax_url,data,function(response){if(response.success){return resolve(response.data)}return reject(response.data)})}}(this))};SV_WC_Apple_Pay_Handler.prototype.render_errors=function(errors){$(".woocommerce-error, .woocommerce-message").remove();this.ui_element.prepend("<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>");this.ui_element.removeClass("processing").unblock();return $("html, body").animate({scrollTop:this.ui_element.offset().top-100},1000)};SV_WC_Apple_Pay_Handler.prototype.block_ui=function(){return this.ui_element.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})};SV_WC_Apple_Pay_Handler.prototype.unblock_ui=function(){return this.ui_element.unblock()};return SV_WC_Apple_Pay_Handler}();window.Square_Apple_Pay_Cart_Handler=function(superClass){extend(Square_Apple_Pay_Cart_Handler,superClass);function Square_Apple_Pay_Cart_Handler(args){this.attach_update_events=bind(this.attach_update_events,this);this.type="cart";this.ui_element=$("form.woocommerce-cart-form").parents("div.woocommerce");Square_Apple_Pay_Cart_Handler.__super__.constructor.call(this,args)}Square_Apple_Pay_Cart_Handler.prototype.attach_update_events=function(){return $(document.body).on("updated_cart_totals",function(_this){return function(){return _this.reset_payment_request()}}(this))};return Square_Apple_Pay_Cart_Handler}(SV_WC_Apple_Pay_Handler);window.Square_Apple_Pay_Checkout_Handler=function(superClass){extend(Square_Apple_Pay_Checkout_Handler,superClass);function Square_Apple_Pay_Checkout_Handler(args){this.attach_update_events=bind(this.attach_update_events,this);this.type="checkout";this.ui_element=$("form.woocommerce-checkout");Square_Apple_Pay_Checkout_Handler.__super__.constructor.call(this,args);this.buttons=".sv-wc-apply-pay-checkout"}Square_Apple_Pay_Checkout_Handler.prototype.attach_update_events=function(){return $(document.body).on("updated_checkout",function(_this){return function(){return _this.reset_payment_request()}}(this))};return Square_Apple_Pay_Checkout_Handler}(SV_WC_Apple_Pay_Handler);return window.Square_Apple_Pay_Product_Handler=function(superClass){extend(Square_Apple_Pay_Product_Handler,superClass);function Square_Apple_Pay_Product_Handler(args){this.type="product";this.ui_element=$("form.cart");Square_Apple_Pay_Product_Handler.__super__.constructor.call(this,args)}return Square_Apple_Pay_Product_Handler}(SV_WC_Apple_Pay_Handler)})}).call(void 0);
assets/js/frontend/wc-square-payment-gateway-my-payment-methods.min.js ADDED
@@ -0,0 +1 @@
 
1
+ "use strict";(function(){var bind=function bind(fn,me){return function(){return fn.apply(me,arguments)}};jQuery(document).ready(function($){"use strict";return window.Square_Payment_Methods_Handler=function(){function Square_Payment_Methods_Handler(args){this.cancel_edit=bind(this.cancel_edit,this);this.save_method=bind(this.save_method,this);this.edit_method=bind(this.edit_method,this);this.id=args.id;this.slug=args.slug;this.i18n=args.i18n;this.ajax_url=args.ajax_url;this.ajax_nonce=args.ajax_nonce;if(!args.has_core_tokens){$(".wc-"+this.slug+"-my-payment-methods").prev(".woocommerce-Message.woocommerce-Message--info").hide()}$(".wc-"+this.slug+"-payment-method-actions .button.tip").tipTip();$(".wc-"+this.slug+"-my-payment-methods").on("click",".wc-"+this.slug+"-payment-method-actions .edit-payment-method",function(_this){return function(event){return _this.edit_method(event)}}(this));$(".wc-"+this.slug+"-my-payment-methods").on("click",".wc-"+this.slug+"-payment-method-actions .save-payment-method",function(_this){return function(event){return _this.save_method(event)}}(this));$(".wc-"+this.slug+"-my-payment-methods").on("click",".wc-"+this.slug+"-payment-method-actions .cancel-edit-payment-method",function(_this){return function(event){return _this.cancel_edit(event)}}(this));$(".wc-"+this.slug+"-my-payment-methods").on("click",".wc-"+this.slug+"-payment-method-actions .delete-payment-method",function(_this){return function(event){if($(event.currentTarget).hasClass("disabled")||!confirm(_this.i18n.delete_ays)){return event.preventDefault()}}}(this));$(".button[href*=\"add-payment-method\"]").click(function(event){if($(this).hasClass("disabled")){return event.preventDefault()}})}Square_Payment_Methods_Handler.prototype.edit_method=function(event){var button,row;event.preventDefault();button=$(event.currentTarget);row=button.parents("tr");row.find(".view").hide();row.find(".edit").show();row.addClass("editing");button.text(this.i18n.cancel_button).removeClass("edit-payment-method").addClass("cancel-edit-payment-method").removeClass("button");button.siblings(".save-payment-method").show();button.siblings(".delete-payment-method").hide();return this.enable_editing_ui()};Square_Payment_Methods_Handler.prototype.save_method=function(event){var button,data,row;event.preventDefault();button=$(event.currentTarget);row=button.parents("tr");this.block_ui();row.next(".error").remove();data={action:"wc_"+this.id+"_save_payment_method",nonce:this.ajax_nonce,token_id:row.data("token-id"),data:row.find("input[name]").serialize()};return $.post(this.ajax_url,data).done(function(_this){return function(response){if(!response.success){return _this.display_error(row,response.data)}if(response.data.is_default){row.siblings().find(".wc-"+_this.slug+"-payment-method-default .view").empty().siblings(".edit").find("input").prop("checked",false)}if(response.data.html!=null){row.replaceWith(response.data.html)}if(response.data.nonce!=null){_this.ajax_nonce=response.data.nonce}return _this.disable_editing_ui()}}(this)).fail(function(_this){return function(jqXHR,textStatus,error){return _this.display_error(row,error)}}(this)).always(function(_this){return function(){return _this.unblock_ui()}}(this))};Square_Payment_Methods_Handler.prototype.cancel_edit=function(event){var button,row;event.preventDefault();button=$(event.currentTarget);row=button.parents("tr");row.find(".view").show();row.find(".edit").hide();row.removeClass("editing");button.removeClass("cancel-edit-payment-method").addClass("edit-payment-method").text(this.i18n.edit_button).addClass("button");button.siblings(".save-payment-method").hide();button.siblings(".delete-payment-method").show();return this.disable_editing_ui()};Square_Payment_Methods_Handler.prototype.enable_editing_ui=function(){$(".wc-"+this.slug+"-my-payment-methods").addClass("editing");return $(".button[href*=\"add-payment-method\"]").addClass("disabled")};Square_Payment_Methods_Handler.prototype.disable_editing_ui=function(){$(".wc-"+this.slug+"-my-payment-methods").removeClass("editing");return $(".button[href*=\"add-payment-method\"]").removeClass("disabled")};Square_Payment_Methods_Handler.prototype.block_ui=function(){return $(".wc-"+this.slug+"-my-payment-methods").parent("div").block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})};Square_Payment_Methods_Handler.prototype.unblock_ui=function(){return $(".wc-"+this.slug+"-my-payment-methods").parent("div").unblock()};Square_Payment_Methods_Handler.prototype.display_error=function(row,error,message){var columns;if(message==null){message=""}console.error(error);if(!message){message=this.i18n.save_error}columns=$(".wc-"+this.slug+"-my-payment-methods thead tr th").size();return $("<tr class=\"error\"><td colspan=\""+columns+"\">"+message+"</td></tr>").insertAfter(row).find("td").delay(8000).slideUp(200)};return Square_Payment_Methods_Handler}()})}).call(void 0);
assets/js/frontend/wc-square-payment-gateway-payment-form.min.js ADDED
@@ -0,0 +1 @@
 
1
+ "use strict";(function(){var indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i<l;i++){if(i in this&&this[i]===item)return i}return-1};jQuery(document).ready(function($){"use strict";return window.Square_Payment_Form_Handler=function(){function Square_Payment_Form_Handler(args){this.id=args.id;this.id_dasherized=args.id_dasherized;this.plugin_id=args.plugin_id;this.type=args.type;this.csc_required=args.csc_required;this.csc_required_for_tokens=args.csc_required_for_tokens;this.enabled_card_types=args.enabled_card_types;if($("form.checkout").length){this.form=$("form.checkout");this.handle_checkout_page()}else if($("form#order_review").length){this.form=$("form#order_review");this.handle_pay_page()}else if($("form#add_payment_method").length){this.form=$("form#add_payment_method");this.handle_add_payment_method_page()}else{console.log("No payment form found!");return}this.params=window.sv_wc_payment_gateway_payment_form_params;if(this.type==="echeck"){this.form.on("click",".js-sv-wc-payment-gateway-echeck-form-check-hint, .js-sv-wc-payment-gateway-echeck-form-sample-check",function(_this){return function(){return _this.handle_sample_check_hint()}}(this))}$(document).trigger("sv_wc_payment_form_handler_init",{id:this.id,instance:this})}Square_Payment_Form_Handler.prototype.handle_checkout_page=function(){if(this.type==="credit-card"){$(document.body).on("updated_checkout",function(_this){return function(){return _this.format_credit_card_inputs()}}(this))}$(document.body).on("updated_checkout",function(_this){return function(){return _this.set_payment_fields()}}(this));$(document.body).on("updated_checkout",function(_this){return function(){return _this.handle_saved_payment_methods()}}(this));return this.form.on("checkout_place_order_"+this.id,function(_this){return function(){return _this.validate_payment_data()}}(this))};Square_Payment_Form_Handler.prototype.handle_pay_page=function(){this.set_payment_fields();if(this.type==="credit-card"){this.format_credit_card_inputs()}this.handle_saved_payment_methods();return this.form.submit(function(_this){return function(){if($("#order_review input[name=payment_method]:checked").val()===_this.id){return _this.validate_payment_data()}}}(this))};Square_Payment_Form_Handler.prototype.handle_add_payment_method_page=function(){this.set_payment_fields();if(this.type==="credit-card"){this.format_credit_card_inputs()}return this.form.submit(function(_this){return function(){if($("#add_payment_method input[name=payment_method]:checked").val()===_this.id){return _this.validate_payment_data()}}}(this))};Square_Payment_Form_Handler.prototype.set_payment_fields=function(){return this.payment_fields=$(".payment_method_"+this.id)};Square_Payment_Form_Handler.prototype.validate_payment_data=function(){var handler,valid;if(this.form.is(".processing")){return false}this.saved_payment_method_selected=this.payment_fields.find(".js-sv-wc-payment-gateway-payment-token:checked").val();valid=this.type==="credit-card"?this.validate_card_data():this.validate_account_data();handler=$(document.body).triggerHandler("sv_wc_payment_form_valid_payment_data",{payment_form:this,passed_validation:valid})!==false;return valid&&handler};Square_Payment_Form_Handler.prototype.format_credit_card_inputs=function(){$(".js-sv-wc-payment-gateway-credit-card-form-account-number").payment("formatCardNumber").change();$(".js-sv-wc-payment-gateway-credit-card-form-expiry").payment("formatCardExpiry").change();$(".js-sv-wc-payment-gateway-credit-card-form-csc").payment("formatCardCVC").change();return $(".js-sv-wc-payment-gateway-credit-card-form-input").on("change paste keyup",function(_this){return function(){return _this.do_inline_credit_card_validation()}}(this))};Square_Payment_Form_Handler.prototype.do_inline_credit_card_validation=function(){var $card_number,$card_type,$csc,$expiry;$card_number=$(".js-sv-wc-payment-gateway-credit-card-form-account-number");$expiry=$(".js-sv-wc-payment-gateway-credit-card-form-expiry");$csc=$(".js-sv-wc-payment-gateway-credit-card-form-csc");$card_type=$.payment.cardType($card_number.val());if(indexOf.call(this.enabled_card_types,$card_type)<0){$card_number.addClass("invalid-card-type")}else{$card_number.removeClass("invalid-card-type")}if($.payment.validateCardExpiry($expiry.payment("cardExpiryVal"))){$expiry.addClass("identified")}else{$expiry.removeClass("identified")}if($.payment.validateCardCVC($csc.val())){return $csc.addClass("identified")}return $csc.removeClass("identified")};Square_Payment_Form_Handler.prototype.validate_card_data=function(){var account_number,csc,errors,expiry;errors=[];csc=this.payment_fields.find(".js-sv-wc-payment-gateway-credit-card-form-csc").val();if(csc!=null){if(csc){if(/\D/.test(csc)){errors.push(this.params.cvv_digits_invalid)}if(csc.length<3||csc.length>4){errors.push(this.params.cvv_length_invalid)}}else if(this.csc_required){if(!this.saved_payment_method_selected||this.csc_required_for_tokens){errors.push(this.params.cvv_missing)}}}if(!this.saved_payment_method_selected){account_number=this.payment_fields.find(".js-sv-wc-payment-gateway-credit-card-form-account-number").val();expiry=$.payment.cardExpiryVal(this.payment_fields.find(".js-sv-wc-payment-gateway-credit-card-form-expiry").val());account_number=account_number.replace(/-|\s/g,"");if(!account_number){errors.push(this.params.card_number_missing)}else{if(account_number.length<12||account_number.length>19){errors.push(this.params.card_number_length_invalid)}if(/\D/.test(account_number)){errors.push(this.params.card_number_digits_invalid)}if(!$.payment.validateCardNumber(account_number)){errors.push(this.params.card_number_invalid)}}if(!$.payment.validateCardExpiry(expiry)){errors.push(this.params.card_exp_date_invalid)}}if(errors.length>0){this.render_errors(errors);return false}this.payment_fields.find(".js-sv-wc-payment-gateway-credit-card-form-account-number").val(account_number);return true};Square_Payment_Form_Handler.prototype.validate_account_data=function(){var account_number,errors,routing_number;if(this.saved_payment_method_selected){return true}errors=[];routing_number=this.payment_fields.find(".js-sv-wc-payment-gateway-echeck-form-routing-number").val();account_number=this.payment_fields.find(".js-sv-wc-payment-gateway-echeck-form-account-number").val();if(!routing_number){errors.push(this.params.routing_number_missing)}else{if(routing_number.length!==9){errors.push(this.params.routing_number_length_invalid)}if(/\D/.test(routing_number)){errors.push(this.params.routing_number_digits_invalid)}}if(!account_number){errors.push(this.params.account_number_missing)}else{if(account_number.length<3||account_number.length>17){errors.push(this.params.account_number_length_invalid)}if(/\D/.test(account_number)){errors.push(this.params.account_number_invalid)}}if(errors.length>0){this.render_errors(errors);return false}this.payment_fields.find(".js-sv-wc-payment-gateway-echeck-form-account-number").val(account_number);return true};Square_Payment_Form_Handler.prototype.render_errors=function(errors){$(".woocommerce-error, .woocommerce-message").remove();this.form.prepend("<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>");this.form.removeClass("processing").unblock();this.form.find(".input-text, select").blur();return $("html, body").animate({scrollTop:this.form.offset().top-100},1000)};Square_Payment_Form_Handler.prototype.handle_saved_payment_methods=function(){var $csc_field,$new_payment_method_selection,csc_required,csc_required_for_tokens,id_dasherized;id_dasherized=this.id_dasherized;csc_required=this.csc_required;csc_required_for_tokens=this.csc_required_for_tokens;$new_payment_method_selection=$("div.js-wc-"+id_dasherized+"-new-payment-method-form");$csc_field=$new_payment_method_selection.find(".js-sv-wc-payment-gateway-credit-card-form-csc").closest(".form-row");$("input.js-wc-"+this.id_dasherized+"-payment-token").change(function(){var tokenized_payment_method_selected;tokenized_payment_method_selected=$("input.js-wc-"+id_dasherized+"-payment-token:checked").val();if(tokenized_payment_method_selected){$new_payment_method_selection.slideUp(200);if(csc_required_for_tokens){$csc_field.removeClass("form-row-last").addClass("form-row-first");return $new_payment_method_selection.after($csc_field)}}else{$new_payment_method_selection.slideDown(200);if(csc_required_for_tokens){$csc_field.removeClass("form-row-first").addClass("form-row-last");return $new_payment_method_selection.find(".js-sv-wc-payment-gateway-credit-card-form-expiry").closest(".form-row").after($csc_field)}}}).change();$("input#createaccount").change(function(){var $parent_row;$parent_row=$("input.js-wc-"+id_dasherized+"-tokenize-payment-method").closest("p.form-row");if($(this).is(":checked")){$parent_row.slideDown();return $parent_row.next().show()}$parent_row.hide();return $parent_row.next().hide()});if(!$("input#createaccount").is(":checked")){return $("input#createaccount").change()}};Square_Payment_Form_Handler.prototype.handle_sample_check_hint=function(){var $sample_check;$sample_check=this.payment_fields.find(".js-sv-wc-payment-gateway-echeck-form-sample-check");if($sample_check.is(":visible")){return $sample_check.slideUp()}return $sample_check.slideDown()};Square_Payment_Form_Handler.prototype.block_ui=function(){return this.form.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})};Square_Payment_Form_Handler.prototype.unblock_ui=function(){return this.form.unblock()};return Square_Payment_Form_Handler}()})}).call(void 0);
assets/js/frontend/wc-square.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";function _toConsumableArray(arr){return _arrayWithoutHoles(arr)||_iterableToArray(arr)||_unsupportedIterableToArray(arr)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _iterableToArray(iter){if(typeof Symbol!=="undefined"&&iter[Symbol.iterator]!=null||iter["@@iterator"]!=null)return Array.from(iter)}function _arrayWithoutHoles(arr){if(Array.isArray(arr))return _arrayLikeToArray(arr)}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_unsupportedIterableToArray(arr,i)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++){arr2[i]=arr[i]}return arr2}function _iterableToArrayLimit(arr,i){var _i=arr==null?null:typeof Symbol!=="undefined"&&arr[Symbol.iterator]||arr["@@iterator"];if(_i==null)return;var _arr=[];var _n=true;var _d=false;var _s,_e;try{for(_i=_i.call(arr);!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break}}catch(err){_d=true;_e=err}finally{try{if(!_n&&_i["return"]!=null)_i["return"]()}finally{if(_d)throw _e}}return _arr}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);Object.defineProperty(Constructor,"prototype",{writable:false});return Constructor}jQuery(document).ready(function($){var WC_Square_Payment_Form_Handler=function(){function WC_Square_Payment_Form_Handler(args){var _this=this;_classCallCheck(this,WC_Square_Payment_Form_Handler);this.id=args.id;this.id_dasherized=args.id_dasherized;this.csc_required=args.csc_required;this.enabled_card_types=args.enabled_card_types;this.square_card_types=args.square_card_types;this.ajax_log_nonce=args.ajax_log_nonce;this.ajax_url=args.ajax_url;this.application_id=args.application_id;this.currency_code=args.currency_code;this.general_error=args.general_error;this.input_styles=args.input_styles;this.is_3ds_enabled=args.is_3d_secure_enabled;this.is_add_payment_method_page=args.is_add_payment_method_page;this.is_checkout_registration_enabled=args.is_checkout_registration_enabled;this.is_user_logged_in=args.is_user_logged_in;this.location_id=args.location_id;this.logging_enabled=args.logging_enabled;this.ajax_wc_checkout_validate_nonce=args.ajax_wc_checkout_validate_nonce;this.is_manual_order_payment=args.is_manual_order_payment;this.current_postal_code_value="";if($("form.checkout").length){this.form=$("form.checkout");this.handle_checkout_page()}else if($("form#order_review").length){this.form=$("form#order_review");this.handle_pay_page()}else if($("form#add_payment_method").length){this.form=$("form#add_payment_method");this.handle_add_payment_method_page()}else{this.log("No payment form found!");return}this.params=window.sv_wc_payment_gateway_payment_form_params;$(document.body).on("checkout_error",function(){$("input[name=wc-square-credit-card-payment-nonce]").val("");$("input[name=wc-square-credit-card-buyer-verification-token]").val("")});$(document.body).on("click","#payment_method_".concat(this.id),function(){if(_this.payment_form){_this.log("Recalculating payment form size");_this.payment_form.recalculateSize()}})}_createClass(WC_Square_Payment_Form_Handler,[{key:"handle_checkout_page",value:function handle_checkout_page(){var _this2=this;$(document.body).on("updated_checkout",function(){return _this2.set_payment_fields()});$(document.body).on("updated_checkout",function(){return _this2.handle_saved_payment_methods()});this.form.on("checkout_place_order_".concat(this.id),function(){return _this2.validate_payment_data()})}},{key:"handle_saved_payment_methods",value:function handle_saved_payment_methods(){var id_dasherized=this.id_dasherized;var form_handler=this;var $new_payment_method_selection=$("div.js-wc-".concat(id_dasherized,"-new-payment-method-form"));$("input.js-wc-".concat(this.id_dasherized,"-payment-token")).on("change",function(){var tokenized_payment_method_selected=$("input.js-wc-".concat(id_dasherized,"-payment-token:checked")).val();if(tokenized_payment_method_selected){$new_payment_method_selection.slideUp(200)}else{$new_payment_method_selection.slideDown(200)}}).trigger("change");$("input#createaccount").on("change",function(e){if($(e.target).is(":checked")){form_handler.show_save_payment_checkbox(id_dasherized)}else{form_handler.hide_save_payment_checkbox(id_dasherized)}});if(!$("input#createaccount").is(":checked")){$("input#createaccount").trigger("change")}if(!this.is_user_logged_in&&!this.is_checkout_registration_enabled){this.hide_save_payment_checkbox(id_dasherized)}}},{key:"handle_pay_page",value:function handle_pay_page(){this.set_payment_fields();this.handle_saved_payment_methods();var self=this;this.form.on("submit",function(){if($("#order_review input[name=payment_method]:checked").val()===self.id){return self.validate_payment_data()}})}},{key:"handle_add_payment_method_page",value:function handle_add_payment_method_page(){this.set_payment_fields();var self=this;this.form.on("submit",function(){if($("#add_payment_method input[name=payment_method]:checked").val()===self.id){return self.validate_payment_data()}})}},{key:"set_payment_fields",value:function set_payment_fields(){if(!$("#wc-".concat(this.id_dasherized,"-account-number-hosted")).length){return}if($("#wc-".concat(this.id_dasherized,"-account-number-hosted")).is("iframe")){this.log("Re-adding payment form");for(var _i=0,_Object$entries=Object.entries(this.form_fields);_i<_Object$entries.length;_i++){var _Object$entries$_i=_slicedToArray(_Object$entries[_i],2),_=_Object$entries$_i[0],field=_Object$entries$_i[1];$(field.attr("id")).replaceWith(field)}this.handle_form_loaded()}else{if(this.payment_form){this.log("Destroying payment form");this.payment_form.destroy();this.payment_form=null}this.log("Building payment form");this.payment_form=new SqPaymentForm(this.get_form_params());this.payment_form.build()}}},{key:"get_form_params",value:function get_form_params(){var _this3=this;this.form_fields={card_number:$("#wc-".concat(this.id_dasherized,"-account-number-hosted")),expiration:$("#wc-".concat(this.id_dasherized,"-expiry-hosted")),csc:$("#wc-".concat(this.id_dasherized,"-csc-hosted")),postal_code:$("#wc-".concat(this.id_dasherized,"-postal-code-hosted"))};return{applicationId:this.application_id,locationId:this.location_id,cardNumber:{elementId:this.form_fields.card_number.attr("id"),placeholder:this.form_fields.card_number.data("placeholder")},expirationDate:{elementId:this.form_fields.expiration.attr("id"),placeholder:this.form_fields.expiration.data("placeholder")},cvv:{elementId:this.form_fields.csc.attr("id"),placeholder:this.form_fields.csc.data("placeholder")},postalCode:{elementId:this.form_fields.postal_code.attr("id"),placeholder:this.form_fields.postal_code.data("placeholder")},inputClass:"wc-".concat(this.id_dasherized,"-payment-field"),inputStyles:this.input_styles,callbacks:{inputEventReceived:function inputEventReceived(e){return _this3.handle_input_event(e)},cardNonceResponseReceived:function cardNonceResponseReceived(errors,nonce,cardData){return _this3.handle_card_nonce_response(errors,nonce,cardData)},unsupportedBrowserDetected:function unsupportedBrowserDetected(){return _this3.handle_unsupported_browser()},paymentFormLoaded:function paymentFormLoaded(){return _this3.handle_form_loaded()}}}}},{key:"handle_form_loaded",value:function handle_form_loaded(){this.log("Payment form loaded");this.payment_form.setPostalCode($("#billing_postcode").val());if($("form.checkout").length||$("#billing_postcode").val()){$(".wc-square-credit-card-card-postal-code-parent").addClass("hidden")}}},{key:"handle_input_event",value:function handle_input_event(e){var $input=$("#"+e.elementId);if(e.eventType==="cardBrandChanged"){this.handle_card_brand_change(e.cardBrand,$input)}if(e.field==="postalCode"){this.current_postal_code_value=e.postalCodeValue;if(e.eventType==="focusClassRemoved"){this.payment_form.setPostalCode(this.current_postal_code_value.trim())}}}},{key:"handle_card_brand_change",value:function handle_card_brand_change(brand,$input){this.log("Card brand changed to ".concat(brand));$input.attr("class",function(i,c){return c.replace(/(^|\s)card-type-\S+/g,"")});var card_class="plain";if(null===brand||"unknown"===brand){brand=""}if(null!==this.square_card_types[brand]){brand=this.square_card_types[brand]}if(brand&&!this.enabled_card_types.includes(brand)){card_class="invalid"}else{card_class=brand}$("input[name=wc-".concat(this.id_dasherized,"-card-type]")).val(brand);$input.addClass("card-type-".concat(card_class))}},{key:"validate_payment_data",value:function validate_payment_data(){if(this.form.is(".processing")){return false}if(this.has_nonce()){this.log("Payment nonce present, placing order");return true}var tokenized_card_id=this.get_tokenized_payment_method_id();if(tokenized_card_id){if(!this.is_3ds_enabled){return true}if(this.has_verification_token()){this.log("Tokenized payment verification token present, placing order");return true}this.log("Requesting verification token for tokenized payment");this.block_ui();this.payment_form.verifyBuyer(tokenized_card_id,this.get_verification_details(),this.handle_verify_buyer_response.bind(this));return false}this.log("Requesting payment nonce");this.block_ui();this.payment_form.requestCardNonce();return false}},{key:"get_tokenized_payment_method_id",value:function get_tokenized_payment_method_id(){return $(".payment_method_".concat(this.id)).find(".js-wc-square-credit-card-payment-token:checked").val()}},{key:"handle_card_nonce_response",value:function handle_card_nonce_response(errors,nonce,cardData){if(errors){return this.handle_errors(errors)}if(!nonce){var message="Nonce is missing from the Square response";this.log(message,"error");this.log_data(message,"response");return this.handle_errors()}this.log("Card data received");this.log(cardData);this.log_data(cardData,"response");if(cardData.last_4){$("input[name=wc-".concat(this.id_dasherized,"-last-four]")).val(cardData.last_4)}if(cardData.exp_month){$("input[name=wc-".concat(this.id_dasherized,"-exp-month]")).val(cardData.exp_month)}if(cardData.exp_year){$("input[name=wc-".concat(this.id_dasherized,"-exp-year]")).val(cardData.exp_year)}if(cardData.billing_postal_code){$("input[name=wc-".concat(this.id_dasherized,"-payment-postcode]")).val(cardData.billing_postal_code)}$("input[name=wc-".concat(this.id_dasherized,"-payment-nonce]")).val(nonce);if(this.is_3ds_enabled){this.log("Verifying buyer");this.payment_form.verifyBuyer(nonce,this.get_verification_details(),this.handle_verify_buyer_response.bind(this));return}this.form.trigger("submit")}},{key:"handle_verify_buyer_response",value:function handle_verify_buyer_response(errors,verification_result){if(errors){$(errors).each(function(index,error){if(!error.field){error.field="none"}});return this.handle_errors(errors)}if(!verification_result||!verification_result.token){var message="Verification token is missing from the Square response";this.log(message,"error");this.log_data(message,"response");return this.handle_errors()}this.log("Verification result received");this.log(verification_result);$("input[name=wc-".concat(this.id_dasherized,"-buyer-verification-token]")).val(verification_result.token);this.form.trigger("submit")}},{key:"get_verification_details",value:function get_verification_details(){var verification_details={billingContact:{familyName:$("#billing_last_name").val()||"",givenName:$("#billing_first_name").val()||"",email:$("#billing_email").val()||"",country:$("#billing_country").val()||"",region:$("#billing_state").val()||"",city:$("#billing_city").val()||"",postalCode:$("#billing_postcode").val()||"",phone:$("#billing_phone").val()||"",addressLines:[$("#billing_address_1").val()||"",$("#billing_address_2").val()||""]},intent:this.get_intent()};if("CHARGE"===verification_details.intent){verification_details.amount=this.get_amount();verification_details.currencyCode=this.currency_code}this.log(verification_details);return verification_details}},{key:"get_intent",value:function get_intent(){var $save_method_input=$("#wc-square-credit-card-tokenize-payment-method");var save_payment_method;if($save_method_input.is("input:checkbox")){save_payment_method=$save_method_input.is(":checked")}else{save_payment_method="true"===$save_method_input.val()}if(!this.get_tokenized_payment_method_id()&&save_payment_method){return"STORE"}return"CHARGE"}},{key:"get_amount",value:function get_amount(){return $("input[name=wc-".concat(this.id_dasherized,"-amount]")).val()}},{key:"handle_unsupported_browser",value:function handle_unsupported_browser(){}},{key:"handle_errors",value:function handle_errors(){var _this4=this;var errors=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;this.log("Error getting payment data","error");$("input[name=wc-square-credit-card-payment-nonce]").val("");$("input[name=wc-square-credit-card-buyer-verification-token]").val("");var messages=[];if(errors){var field_order=["none","cardNumber","expirationDate","cvv","postalCode"];if(errors.length>=1){errors.sort(function(a,b){return field_order.indexOf(a.field)-field_order.indexOf(b.field)})}$(errors).each(function(index,error){if("UNSUPPORTED_CARD_BRAND"===error.type||"VALIDATION_ERROR"===error.type){return messages.push(error.message.replace(/CVV/,"CSC"))}return _this4.log_data(errors,"response")})}if(messages.length===0){messages.push(this.general_error)}if(!this.is_add_payment_method_page&&!this.is_manual_order_payment){this.render_checkout_errors(messages)}else{this.render_errors(messages)}this.unblock_ui()}},{key:"render_errors",value:function render_errors(errors){$(".woocommerce-error, .woocommerce-message").remove();this.form.prepend("<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>");this.form.removeClass("processing").unblock();this.form.find(".input-text, select").trigger("blur");$("html, body").animate({scrollTop:this.form.offset().top-100},1000)}},{key:"block_ui",value:function block_ui(){this.form.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})}},{key:"unblock_ui",value:function unblock_ui(){return this.form.unblock()}},{key:"hide_save_payment_checkbox",value:function hide_save_payment_checkbox(id_dasherized){var $parent_row=$("input.js-wc-".concat(id_dasherized,"-tokenize-payment-method")).closest("p.form-row");$parent_row.hide();$parent_row.next().hide()}},{key:"show_save_payment_checkbox",value:function show_save_payment_checkbox(id_dasherized){var $parent_row=$("input.js-wc-".concat(id_dasherized,"-tokenize-payment-method")).closest("p.form-row");$parent_row.slideDown();$parent_row.next().show()}},{key:"has_nonce",value:function has_nonce(){return $("input[name=wc-".concat(this.id_dasherized,"-payment-nonce]")).val()}},{key:"has_verification_token",value:function has_verification_token(){return $("input[name=wc-".concat(this.id_dasherized,"-buyer-verification-token]")).val()}},{key:"log_data",value:function log_data(data,type){if(!this.logging_enabled){return}var ajax_data={action:"wc_"+this.id+"_log_js_data",security:this.ajax_log_nonce,type:type,data:data};$.ajax({url:this.ajax_url,data:ajax_data})}},{key:"log",value:function log(message){var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"notice";if(!this.logging_enabled){return}if("error"===type){console.error("Square Error: "+message)}else{console.log("Square: "+message)}}},{key:"render_checkout_errors",value:function render_checkout_errors(square_errors){var _this5=this;var ajax_url=wc_cart_fragments_params.wc_ajax_url.toString().replace("%%endpoint%%",this.id+"_checkout_handler");var square_handler=this;var form_data=this.form.serializeArray();form_data.push({name:"wc_"+this.id+"_checkout_validate_nonce",value:this.ajax_wc_checkout_validate_nonce});return $.ajax({url:ajax_url,method:"post",cache:false,data:form_data,complete:function complete(response){var result=response.responseJSON;if(result.hasOwnProperty("result")&&"failure"===result.result){$(result.messages).map(function(message){var errors=[];$(message).children("li").each(function(){errors.push($(_this5).text().trim())});return square_errors.unshift.apply(square_errors,errors)})}else if(result.hasOwnProperty("success")&&!result.success){square_errors.unshift.apply(square_errors,_toConsumableArray(result.data.messages))}square_handler.render_errors(square_errors)}})}}]);return WC_Square_Payment_Form_Handler}();window.WC_Square_Payment_Form_Handler=WC_Square_Payment_Form_Handler});
1
+ "use strict";jQuery(document).ready($=>{class WC_Square_Payment_Form_Handler{constructor(args){this.id=args.id;this.id_dasherized=args.id_dasherized;this.csc_required=args.csc_required;this.enabled_card_types=args.enabled_card_types;this.square_card_types=args.square_card_types;this.ajax_log_nonce=args.ajax_log_nonce;this.ajax_url=args.ajax_url;this.application_id=args.application_id;this.currency_code=args.currency_code;this.general_error=args.general_error;this.input_styles=args.input_styles;this.is_3ds_enabled=args.is_3d_secure_enabled;this.is_add_payment_method_page=args.is_add_payment_method_page;this.is_checkout_registration_enabled=args.is_checkout_registration_enabled;this.is_user_logged_in=args.is_user_logged_in;this.location_id=args.location_id;this.logging_enabled=args.logging_enabled;this.ajax_wc_checkout_validate_nonce=args.ajax_wc_checkout_validate_nonce;this.is_manual_order_payment=args.is_manual_order_payment;this.current_postal_code_value="";if($("form.checkout").length){this.form=$("form.checkout");this.handle_checkout_page()}else if($("form#order_review").length){this.form=$("form#order_review");this.handle_pay_page()}else if($("form#add_payment_method").length){this.form=$("form#add_payment_method");this.handle_add_payment_method_page()}else{this.log("No payment form found!");return}this.params=window.sv_wc_payment_gateway_payment_form_params;$(document.body).on("checkout_error",()=>{$("input[name=wc-square-credit-card-payment-nonce]").val("");$("input[name=wc-square-credit-card-buyer-verification-token]").val("")});$(document.body).on("change","#payment_method_".concat(this.id),()=>{if(this.payment_form){this.log("Recalculating payment form size");this.payment_form.recalculateSize()}})}handle_checkout_page(){$(document.body).on("updated_checkout",()=>this.set_payment_fields());$(document.body).on("updated_checkout",()=>this.handle_saved_payment_methods());this.form.on("checkout_place_order_".concat(this.id),()=>this.validate_payment_data())}handle_saved_payment_methods(){var id_dasherized=this.id_dasherized;var form_handler=this;var $new_payment_method_selection=$("div.js-wc-".concat(id_dasherized,"-new-payment-method-form"));$("input.js-wc-".concat(this.id_dasherized,"-payment-token")).on("change",()=>{var tokenized_payment_method_selected=$("input.js-wc-".concat(id_dasherized,"-payment-token:checked")).val();if(tokenized_payment_method_selected){$new_payment_method_selection.slideUp(200)}else{$new_payment_method_selection.slideDown(200)}}).trigger("change");$("input#createaccount").on("change",e=>{if($(e.target).is(":checked")){form_handler.show_save_payment_checkbox(id_dasherized)}else{form_handler.hide_save_payment_checkbox(id_dasherized)}});if(!$("input#createaccount").is(":checked")){$("input#createaccount").trigger("change")}if(!this.is_user_logged_in&&!this.is_checkout_registration_enabled){this.hide_save_payment_checkbox(id_dasherized)}}handle_pay_page(){this.set_payment_fields();this.handle_saved_payment_methods();var self=this;this.form.on("submit",function(){if($("#order_review input[name=payment_method]:checked").val()===self.id){return self.validate_payment_data()}})}handle_add_payment_method_page(){this.set_payment_fields();var self=this;this.form.on("submit",function(){if($("#add_payment_method input[name=payment_method]:checked").val()===self.id){return self.validate_payment_data()}})}set_payment_fields(){if(this.payment_form){this.log("Destroying payment form");this.payment_form.destroy().then(()=>{this.log("Re-building payment form");this.initializeCard(this.payments)});return}this.log("Building payment form");var{applicationId,locationId}=this.get_form_params();this.payments=window.Square.payments(applicationId,locationId);this.initializeCard(this.payments)}initializeCard(payments){var defaultPostalCode=$("#billing_postcode").val();defaultPostalCode=defaultPostalCode||"";payments.card({postalCode:defaultPostalCode}).then(card=>{card.attach("#wc-square-credit-card-container");this.payment_form=card;this.log("Payment form loaded")})}get_form_params(){return{applicationId:this.application_id,locationId:this.location_id}}validate_payment_data(){if(this.form.is(".processing")){return false}if(this.has_nonce()){this.log("Payment nonce present, placing order");return true}var tokenized_card_id=this.get_tokenized_payment_method_id();if(tokenized_card_id){if(!this.is_3ds_enabled){return true}if(this.has_verification_token()){this.log("Tokenized payment verification token present, placing order");return true}this.log("Requesting verification token for tokenized payment");this.block_ui();this.payments.verifyBuyer(tokenized_card_id,this.get_verification_details()).then(verificationResult=>{this.handle_verify_buyer_response(false,verificationResult)});return false}this.log("Requesting payment nonce");this.block_ui();this.handleSubmission();return false}handleSubmission(){var tokenPromise=this.payment_form.tokenize();tokenPromise.then(tokenResult=>{var{token,details,status}=tokenResult;if(status==="OK"){this.handle_card_nonce_response(token,details)}else{if(tokenResult.errors){this.handle_errors(tokenResult.errors)}}})}get_tokenized_payment_method_id(){return $(".payment_method_".concat(this.id)).find(".js-wc-square-credit-card-payment-token:checked").val()}handle_card_nonce_response(nonce,details){var{card:cardData,billing}=details;if(!nonce){var message="Nonce is missing from the Square response";this.log(message,"error");this.log_data(message,"response");return this.handle_errors()}this.log("Card data received");this.log(cardData);this.log_data(cardData,"response");if(cardData.last4){$("input[name=wc-".concat(this.id_dasherized,"-last-four]")).val(cardData.last4)}if(cardData.expMonth){$("input[name=wc-".concat(this.id_dasherized,"-exp-month]")).val(cardData.expMonth)}if(cardData.expYear){$("input[name=wc-".concat(this.id_dasherized,"-exp-year]")).val(cardData.expYear)}if(billing.postalCode){$("input[name=wc-".concat(this.id_dasherized,"-payment-postcode]")).val(billing.postalCode)}if(cardData.brand){$("input[name=wc-".concat(this.id_dasherized,"-card-type]")).val(cardData.brand)}$("input[name=wc-".concat(this.id_dasherized,"-payment-nonce]")).val(nonce);if(this.is_3ds_enabled){this.log("Verifying buyer");this.payments.verifyBuyer(nonce,this.get_verification_details()).then(verificationResult=>{this.handle_verify_buyer_response(false,verificationResult)});return}this.form.trigger("submit")}handle_verify_buyer_response(errors,verification_result){if(errors){$(errors).each((index,error)=>{if(!error.field){error.field="none"}});return this.handle_errors(errors)}if(!verification_result||!verification_result.token){var message="Verification token is missing from the Square response";this.log(message,"error");this.log_data(message,"response");return this.handle_errors()}this.log("Verification result received");this.log(verification_result);$("input[name=wc-".concat(this.id_dasherized,"-buyer-verification-token]")).val(verification_result.token);this.form.trigger("submit")}get_verification_details(){var verification_details={billingContact:{familyName:$("#billing_last_name").val()||"",givenName:$("#billing_first_name").val()||"",email:$("#billing_email").val()||"",country:$("#billing_country").val()||"",region:$("#billing_state").val()||"",city:$("#billing_city").val()||"",postalCode:$("#billing_postcode").val()||"",phone:$("#billing_phone").val()||"",addressLines:[$("#billing_address_1").val()||"",$("#billing_address_2").val()||""]},intent:this.get_intent()};if("CHARGE"===verification_details.intent){verification_details.amount=this.get_amount();verification_details.currencyCode=this.currency_code}this.log(verification_details);return verification_details}get_intent(){var $save_method_input=$("#wc-square-credit-card-tokenize-payment-method");var save_payment_method;if($save_method_input.is("input:checkbox")){save_payment_method=$save_method_input.is(":checked")}else{save_payment_method="true"===$save_method_input.val()}if(!this.get_tokenized_payment_method_id()&&save_payment_method){return"STORE"}return"CHARGE"}get_amount(){return $("input[name=wc-".concat(this.id_dasherized,"-amount]")).val()}handle_errors(){var errors=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;this.log("Error getting payment data","error");$("input[name=wc-square-credit-card-payment-nonce]").val("");$("input[name=wc-square-credit-card-buyer-verification-token]").val("");var messages=[];if(errors){var field_order=["none","cardNumber","expirationDate","cvv","postalCode"];if(errors.length>=1){errors.sort((a,b)=>{return field_order.indexOf(a.field)-field_order.indexOf(b.field)})}$(errors).each((index,error)=>{if("UNSUPPORTED_CARD_BRAND"===error.type||"VALIDATION_ERROR"===error.type){return messages.push(error.message)}return this.log_data(errors,"response")})}if(messages.length===0){messages.push(this.general_error)}if(!this.is_add_payment_method_page&&!this.is_manual_order_payment){this.render_checkout_errors(messages)}else{this.render_errors(messages)}this.unblock_ui()}render_errors(errors){$(".woocommerce-error, .woocommerce-message").remove();this.form.prepend("<ul class=\"woocommerce-error\"><li>"+errors.join("</li><li>")+"</li></ul>");this.form.removeClass("processing").unblock();this.form.find(".input-text, select").trigger("blur");$("html, body").animate({scrollTop:this.form.offset().top-100},1000)}block_ui(){this.form.block({message:null,overlayCSS:{background:"#fff",opacity:0.6}})}unblock_ui(){return this.form.unblock()}hide_save_payment_checkbox(id_dasherized){var $parent_row=$("input.js-wc-".concat(id_dasherized,"-tokenize-payment-method")).closest("p.form-row");$parent_row.hide();$parent_row.next().hide()}show_save_payment_checkbox(id_dasherized){var $parent_row=$("input.js-wc-".concat(id_dasherized,"-tokenize-payment-method")).closest("p.form-row");$parent_row.slideDown();$parent_row.next().show()}has_nonce(){return $("input[name=wc-".concat(this.id_dasherized,"-payment-nonce]")).val()}has_verification_token(){return $("input[name=wc-".concat(this.id_dasherized,"-buyer-verification-token]")).val()}log_data(data,type){if(!this.logging_enabled){return}var ajax_data={action:"wc_"+this.id+"_log_js_data",security:this.ajax_log_nonce,type,data};$.ajax({url:this.ajax_url,data:ajax_data})}log(message){var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"notice";if(!this.logging_enabled){return}if("error"===type){console.error("Square Error: "+message)}else{console.log("Square: "+message)}}render_checkout_errors(square_errors){var ajax_url=wc_cart_fragments_params.wc_ajax_url.toString().replace("%%endpoint%%",this.id+"_checkout_handler");var square_handler=this;var form_data=this.form.serializeArray();form_data.push({name:"wc_"+this.id+"_checkout_validate_nonce",value:this.ajax_wc_checkout_validate_nonce});return $.ajax({url:ajax_url,method:"post",cache:false,data:form_data,complete:response=>{var result=response.responseJSON;if(result.hasOwnProperty("result")&&"failure"===result.result){$(result.messages).map(message=>{var errors=[];$(message).children("li").each(()=>{errors.push($(this).text().trim())});return square_errors.unshift(...errors)})}else if(result.hasOwnProperty("success")&&!result.success){square_errors.unshift(...result.data.messages)}square_handler.render_errors(square_errors)}})}}window.WC_Square_Payment_Form_Handler=WC_Square_Payment_Form_Handler});
build/index.asset.php CHANGED
@@ -1 +1 @@
1
- <?php return array('dependencies' => array('react', 'wc-blocks-registry', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '3b8457821db6fd492c3826662c0891b7');
1
+ <?php return array('dependencies' => array('react', 'wc-blocks-registry', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'fb7d2eefc86f7c746ceb39c3c41889c7');
build/index.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function r(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,r),a.l=!0,a.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)r.d(n,a,function(t){return e[t]}.bind(null,a));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=30)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=function(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=window.React},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t};Object.defineProperty(t,"__esModule",{value:!0});var a=n(r(2));t.Context=a.createContext({applePayState:"loading",formId:"",googlePayState:"loading",masterpassState:"loading",onCreateNonce:function(){},onVerifyBuyer:function(e,t,r){}}),t.default=t.Context},function(e,t,r){"use strict";function n(e){for(var r in e)t.hasOwnProperty(r)||(t[r]=e[r])}Object.defineProperty(t,"__esModule",{value:!0});var a=r(8);n(r(15)),n(r(3)),n(r(16)),n(r(17)),n(r(18)),n(r(19)),n(r(20)),n(r(21)),n(r(22)),n(r(23)),n(r(24)),n(r(8)),t.default=a.SquarePaymentForm},function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.regeneratorRuntime},function(e,t,r){var n=r(25),a=r(26),o=r(27),i=r(29);e.exports=function(e,t){return n(e)||a(e,t)||o(e,t)||i()},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(14)),l=a(r(3));t.SquarePaymentForm=function(e){var t=o.useState("loading"),r=t[0],n=t[1],a=o.useState("loading"),c=a[0],u=a[1],s=o.useState("loading"),d=s[0],f=s[1],p=o.useState(""),m=p[0],v=p[1],y=o.useState(!1),b=y[0],g=y[1],h=o.useState(void 0),_=h[0],O=h[1],C=o.useState(!1),S=C[0],E=C[1],j=i.default((function(t,r,n,a,o,i){!t&&e.createVerificationDetails?_&&_.verifyBuyer(r,e.createVerificationDetails(),(function(t,l){e.cardNonceResponseReceived(t?[t]:null,r,n,l?l.token:void 0,a,o,i)})):e.cardNonceResponseReceived(t,r,n,"",a,o,i)}));function x(t){var r=Object.keys(t);r.includes("masterpass")&&f(!0===t.masterpass?"ready":"unavailable"),r.includes("applePay")&&n(!0===t.applePay?"ready":"unavailable"),r.includes("googlePay")&&u(!0===t.googlePay?"ready":"unavailable"),e.methodsSupported&&e.methodsSupported(t)}var w=function(){E(!0),e.paymentFormLoaded&&e.paymentFormLoaded()};if(o.useEffect((function(){S&&_&&(_.recalculateSize(),e.postalCode&&_.setPostalCode(e.postalCode()),e.focusField&&_.focus(e.focusField()))}),[S,_]),o.useEffect((function(){!function(t,r){if(document.getElementById("sq-payment-form-script")&&"function"==typeof SqPaymentForm)t&&t();else{var n=document.createElement("script");n.id="sq-payment-form-script",e.sandbox?n.src="https://js.squareupsandbox.com/v2/paymentform":n.src="https://js.squareup.com/v2/paymentform",n.onload=function(){t&&t()},n.onerror=function(){r&&r()},document.body.appendChild(n)}}((function(){return g(!0)}),(function(){return v("Unable to load Square payment library")}))}),[]),o.useEffect((function(){return function(){if(!(!b||_||m.length>0))try{var t=new SqPaymentForm(function(e){var t={apiWrapper:e.apiWrapper,applicationId:e.applicationId,autoBuild:!1,callbacks:{cardNonceResponseReceived:e.cardNonceResponseReceived?j:null,createPaymentRequest:e.createPaymentRequest,inputEventReceived:e.inputEventReceived,methodsSupported:x,paymentFormLoaded:w,shippingContactChanged:e.shippingContactChanged,shippingOptionChanged:e.shippingOptionChanged,unsupportedBrowserDetected:e.unsupportedBrowserDetected},locationId:e.locationId};return document.getElementById(e.formId+"-sq-card")?t.card={elementId:e.formId+"-sq-card",inputStyle:e.inputStyles&&e.inputStyles[0]}:document.getElementById(e.formId+"-sq-gift-card")?(t.giftCard={elementId:e.formId+"-sq-gift-card",placeholder:e.placeholderGiftCard||"• • • • • • • • • • • • • • • •"},t.inputClass=e.inputClass||"sq-input",t.inputStyles=e.inputStyles):(t.inputClass=e.inputClass||"sq-input",t.inputStyles=e.inputStyles,document.getElementById(e.formId+"-sq-apple-pay")&&(t.applePay={elementId:e.formId+"-sq-apple-pay"}),document.getElementById(e.formId+"-sq-google-pay")&&(t.googlePay={elementId:e.formId+"-sq-google-pay"}),document.getElementById(e.formId+"-sq-masterpass")&&(t.masterpass={elementId:e.formId+"-sq-masterpass"}),document.getElementById(e.formId+"-sq-card-number")&&(t.cardNumber={elementId:e.formId+"-sq-card-number",placeholder:e.placeholderCreditCard||"• • • • • • • • • • • • • • • •"}),document.getElementById(e.formId+"-sq-cvv")&&(t.cvv={elementId:e.formId+"-sq-cvv",placeholder:e.placeholderCVV||"CVV "}),document.getElementById(e.formId+"-sq-postal-code")?t.postalCode={elementId:e.formId+"-sq-postal-code",placeholder:e.placeholderPostal||"12345"}:t.postalCode=!1,document.getElementById(e.formId+"-sq-expiration-date")&&(t.expirationDate={elementId:e.formId+"-sq-expiration-date",placeholder:e.placeholderExpiration||"MM/YY"})),t}(e));t.build(),O(t)}catch(e){var r=e.message||"Unable to build Square payment form";v(r)}}(),function(){_&&(_.destroy(),O(void 0))}}),[b]),o.useEffect((function(){if(_&&"ready"===d){var t=document.getElementById(e.formId+"-sq-masterpass");if(t){var r=_.masterpassImageUrl();t.style.display="inline-block",t.style.backgroundImage="url("+r+")"}}}),[_,d]),m)return o.default.createElement("div",{className:"sq-payment-form"},o.default.createElement("div",{className:"sq-error-message"},m));var P={applePayState:r,formId:e.formId,googlePayState:c,masterpassState:d,onCreateNonce:function(){_&&_.requestCardNonce()},onVerifyBuyer:function(e,t,r){_&&_.verifyBuyer(e,t,r)}};return o.default.createElement(l.default.Provider,{value:P},o.default.createElement("div",{id:e.formId,className:"sq-payment-form"},e.children))},t.SquarePaymentForm.defaultProps={apiWrapper:"reactjs/0.7.2",formId:"sq-payment-form",inputStyles:[{_mozOsxFontSmoothing:"grayscale",_webkitFontSmoothing:"antialiased",backgroundColor:"transparent",color:"#373F4A",fontFamily:"Helvetica Neue",fontSize:"16px",lineHeight:"24px",padding:"16px",placeholderColor:"#CCC"}],sandbox:!1}},function(e,t){e.exports=window.wc.wcBlocksRegistry},function(e,t,r){var n=r(13);e.exports=function(e,t){if(null==e)return{};var r,a,o=n(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a<i.length;a++)r=i[a],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){function r(e,t,r,n,a,o,i){try{var l=e[o](i),c=l.value}catch(e){return void r(e)}l.done?t(c):Promise.resolve(c).then(n,a)}e.exports=function(e){return function(){var t=this,n=arguments;return new Promise((function(a,o){var i=e.apply(t,n);function l(e){r(i,a,o,l,c,"next",e)}function c(e){r(i,a,o,l,c,"throw",e)}l(void 0)}))}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=window.wc.wcSettings},function(e,t){e.exports=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=r(2);t.default=function(e){var t=n.useRef(e);return n.useLayoutEffect((function(){t.current=e}),[e]),n.useCallback((function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];return t.current.apply(t,e)}),[])}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.ApplePayButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-apple-pay",className:"sq-apple-pay",style:{display:"ready"===t.applePayState?"block":"none"}}),"loading"===t.applePayState&&e.loadingView,"unavailable"===t.applePayState&&e.unavailableView)}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.CreditCardCVVInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-cvv"}))},t.CreditCardCVVInput.defaultProps={label:"CVV"}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.CreditCardExpirationDateInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-expiration-date"}))},t.CreditCardExpirationDateInput.defaultProps={label:"Expiration"}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.CreditCardNumberInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-card-number"}))},t.CreditCardNumberInput.defaultProps={label:"Credit Card"}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.CreditCardPostalCodeInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-postal-code"}))},t.CreditCardPostalCodeInput.defaultProps={label:"Postal"}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.CreditCardSubmitButton=function(e){var t=o.useContext(i.default);return o.default.createElement("button",{className:"sq-creditcard",onClick:t.onCreateNonce},e.children?e.children:"Pay")}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.GiftCardInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-gift-card"}))},t.GiftCardInput.defaultProps={label:"Gift Card"}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.GooglePayButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-google-pay",className:"sq-google-pay",style:{display:"ready"===t.googlePayState?"block":"none"}}),"loading"===t.googlePayState&&e.loadingView,"unavailable"===t.googlePayState&&e.unavailableView)}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.MasterpassButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-masterpass",className:"sq-masterpass",style:{display:"ready"===t.masterpassState?"block":"none"}}),"loading"===t.masterpassState&&e.loadingView,"unavailable"===t.masterpassState&&e.unavailableView)}},function(e,t,r){"use strict";var n=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2)),i=a(r(3));t.SimpleCard=function(){var e=o.useContext(i.default);return o.default.createElement("div",{id:e.formId+"-sq-card"})}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,a,o=[],_n=!0,i=!1;try{for(r=r.call(e);!(_n=(n=r.next()).done)&&(o.push(n.value),!t||o.length!==t);_n=!0);}catch(e){i=!0,a=e}finally{try{_n||null==r.return||r.return()}finally{if(i)throw a}}return o}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,r){var n=r(28);e.exports=function(e,t){if(e){if("string"==typeof e)return n(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,r){"use strict";r.r(t);var n=r(9),a=r(10),o=r.n(a),i=r(0),l=r(5),c=r(4),u=r(1),s=r.n(u),d=r(11),f=r.n(d),p=r(6),m=r.n(p),v=r(12);function y(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return b(e,void 0);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?b(e,void 0):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return i=e.done,e},e:function(e){l=!0,o=e},f:function(){try{i||null==r.return||r.return()}finally{if(l)throw o}}}}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}var g=null,h=function(){if(null!==g)return g;var e=Object(v.getSetting)("square_credit_card_data",null);if(!e)throw new Error("Square initialization data is not available");return g={title:e.title||"",applicationId:e.application_id||"",locationId:e.location_id||"",isSandbox:e.is_sandbox||!1,is3dsEnabled:e.is_3ds_enabled||!1,inputStyles:e.input_styles||[],availableCardTypes:e.available_card_types||{},loggingEnabled:e.logging_enabled||!1,generalError:e.general_error||"",showSavedCards:e.show_saved_cards||!1,showSaveOption:e.show_save_option||!1,supports:e.supports||{}}},_=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{logs:[],notices:[]},r=!1;if(e){var n=["none","cardNumber","expirationDate","cvv","postalCode"];e.length>=1&&e.sort((function(e,t){return n.indexOf(e.field)-n.indexOf(t.field)}));var a,o=y(e);try{for(o.s();!(a=o.n()).done;){var i=a.value;"UNSUPPORTED_CARD_BRAND"===i.type||"VALIDATION_ERROR"===i.type?(t.notices.push(i.message.replace(/CVV/,"CSC")),r=!0):C(i,t)}}catch(e){o.e(e)}finally{o.f()}}r||t.notices.push(h().generalError)},O=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"notice";h().loggingEnabled&&("error"===t?console.error(e):console.log(e))},C=function(e,t){h().loggingEnabled&&t&&t.logs.push(e)};function S(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function E(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?S(Object(r),!0).forEach((function(t){s()(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):S(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}var j=function(e){var t=e.checkoutFormHandler,r=e.eventRegistration,n=e.emitResponse,a=Object(i.useContext)(c.Context),o=r.onPaymentProcessing,l=r.onCheckoutAfterProcessingWithError,u=r.onCheckoutAfterProcessingWithSuccess;return function(e,t,r,n,a,o){var l=Object(i.useRef)(r);Object(i.useEffect)((function(){l.current=r}),[r]),Object(i.useEffect)((function(){return e(function(){var e=f()(m.a.mark((function e(){var r,i,c,u,s,d;return m.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r={type:t.responseTypes.SUCCESS},i={nonce:"",notices:[],logs:[]},e.next=4,a(l.current);case 4:if(c=e.sent,u=E(E({},i),c),s=u.token||u.nonce,!h().is3dsEnabled||!s){e.next=14;break}return e.next=10,o(l.current,s);case 10:d=e.sent,u.verificationToken=d.verificationToken||"",u.logs=u.logs.concat(d.log||[]),u.errors=u.notices.concat(d.errors||[]);case 14:return s||u.logs.length>0?r.meta={paymentMethodData:n(u)}:u.notices.length>0&&(r.type=t.responseTypes.ERROR,r.message=u.notices),e.abrupt("return",r);case 16:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}())}),[e,t.responseTypes.SUCCESS,t.responseTypes.ERROR,a,o,n])}(o,n,a,t.getPaymentMethodData,t.createNonce,t.verifyBuyer),function(e,t,r){Object(i.useEffect)((function(){var n=function(e){var t={type:r.responseTypes.SUCCESS},n=e.processingResponse,a=n.paymentStatus,o=n.paymentDetails;return a===r.responseTypes.ERROR&&o.checkoutNotices&&(t={type:r.responseTypes.ERROR,message:JSON.parse(o.checkoutNotices),messageContext:r.noticeContexts.PAYMENTS,retry:!0}),t},a=e(n),o=t(n);return function(){a(),o()}}),[e,t,r.noticeContexts.PAYMENTS,r.responseTypes.ERROR,r.responseTypes.SUCCESS])}(l,u,n),null},x=r(7),w=r.n(x);function P(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return I(e,void 0);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?I(e,void 0):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return i=e.done,e},e:function(e){l=!0,o=e},f:function(){try{i||null==r.return||r.return()}finally{if(l)throw o}}}}function I(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}var q=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,n=Object(i.useState)(!1),a=w()(n,2),o=a[0],l=a[1],c=Object(i.useState)(""),u=w()(c,2),d=u[0],f=u[1],p=Object(i.useRef)(null),m=Object(i.useRef)(null),v=Object(i.useMemo)((function(){var n=t&&!r?"STORE":"CHARGE",a={billingContact:{familyName:e.billingData.last_name||"",givenName:e.billingData.first_name||"",email:e.billingData.email||"",country:e.billingData.country||"",region:e.billingData.state||"",city:e.billingData.city||"",postalCode:e.billingData.postcode||"",phone:e.billingData.phone||"",addressLines:[e.billingData.address_1||"",e.billingData.address_2||""]},intent:n};return"CHARGE"===n&&(a.amount=(e.cartTotal.value/100).toString(),a.currencyCode=e.currency.code),a}),[e.billingData,e.cartTotal.value,e.currency.code,t,r]),y=Object(i.useCallback)((function(e){var n,a,o,i=e.cardData,l=e.nonce,c=e.verificationToken,u=e.notices,f=e.logs;return o={},s()(o,"wc-".concat("square-credit-card","-card-type"),d||""),s()(o,"wc-".concat("square-credit-card","-last-four"),(null==i?void 0:i.last_4)||""),s()(o,"wc-".concat("square-credit-card","-exp-month"),(null==i||null===(n=i.exp_month)||void 0===n?void 0:n.toString())||""),s()(o,"wc-".concat("square-credit-card","-exp-year"),(null==i||null===(a=i.exp_year)||void 0===a?void 0:a.toString())||""),s()(o,"wc-".concat("square-credit-card","-payment-postcode"),(null==i?void 0:i.billing_postal_code)||""),s()(o,"wc-".concat("square-credit-card","-payment-nonce"),l||""),s()(o,"wc-".concat("square-credit-card","-payment-token"),r||""),s()(o,"wc-".concat("square-credit-card","-buyer-verification-token"),c||""),s()(o,"wc-".concat("square-credit-card","-tokenize-payment-method"),t||!1),s()(o,"log-data",f.length>0?JSON.stringify(f):""),s()(o,"checkout-notices",u.length>0?JSON.stringify(u):""),o}),[d,t,r]),b=function(e,t,r){var n={notices:[],logs:[]};e?_(e,n):t?(C(r,n),O("Card data received"),O(r),n.cardData=r,n.nonce=t):(C("Nonce is missing from the Square response",n),O("Nonce is missing from the Square response","error"),_([],n)),p.current&&p.current(n)},g=Object(i.useCallback)((function(e){if(!r){var t=new Promise((function(e){return p.current=e}));return e.onCreateNonce(),t}return Promise.resolve({token:r})}),[r]),S=Object(i.useCallback)((function(e,t){var r=new Promise((function(e){return m.current=e}));return e.onVerifyBuyer(t,v,E),r}),[v,E]),E=Object(i.useCallback)((function(e,t){var r={notices:[],logs:[]};if(e){var n,a=P(e);try{for(a.s();!(n=a.n()).done;){var o=n.value;o.field||(o.field="none")}}catch(e){a.e(e)}finally{a.f()}_(e,r)}t&&t.token?r.verificationToken=t.token:(C("Verification token is missing from the Square response",r),O("Verification token is missing from the Square response","error"),_([],r)),m.current&&m.current(r)}),[m]),j=Object(i.useCallback)((function(e){if("cardBrandChanged"===e.eventType){var t=e.cardBrand,r="plain";null!==t&&"unknown"!==t||(r=""),null!==h().availableCardTypes[t]&&(r=h().availableCardTypes[t]),O("Card brand changed to ".concat(t)),f(r)}}),[]),x=Object(i.useCallback)((function(){return e.billingData.postcode||""}),[e.billingData.postcode]);return{cardNonceResponseReceived:b,handleInputReceived:j,isLoaded:o,setLoaded:l,getPostalCode:x,cardType:d,createNonce:g,verifyBuyer:S,getPaymentMethodData:y}},M=function(e){var t=e.cardType;return Object(i.createElement)("fieldset",{id:"wc-square-credit-card-credit-card-form"},Object(i.createElement)("span",{className:"sq-label"},Object(l.__)("Card Number","woocommerce-square")),Object(i.createElement)("div",{id:"wc-square-credit-card-account-number-hosted",className:"wc-square-credit-card-hosted-field ".concat(t?"card-type-".concat(t):"")},Object(i.createElement)(c.CreditCardNumberInput,{label:""})),Object(i.createElement)("div",{className:"sq-form-third"},Object(i.createElement)("span",{className:"sq-label"},Object(l.__)("Expiration (MM/YY)","woocommerce-square")),Object(i.createElement)("div",{id:"wc-square-credit-card-expiry-hosted",className:"wc-square-credit-card-hosted-field"},Object(i.createElement)(c.CreditCardExpirationDateInput,{label:""}))),Object(i.createElement)("div",{className:"sq-form-third"},Object(i.createElement)("span",{className:"sq-label"},Object(l.__)("Card Security Code","woocommerce-square")),Object(i.createElement)("div",{id:"wc-square-credit-card-csc-hosted",className:"wc-square-credit-card-hosted-field"},Object(i.createElement)(c.CreditCardCVVInput,{label:""}))),Object(i.createElement)("div",{className:"sq-form-third"},Object(i.createElement)("span",{className:"sq-label"},Object(l.__)("Postal code","woocommerce-square")),Object(i.createElement)("div",{id:"wc-square-credit-card-postal-code-hosted",className:"wc-square-credit-card-hosted-field"},Object(i.createElement)(c.CreditCardPostalCodeInput,{label:""}))))},R=function(e){var t=e.billing,r=e.eventRegistration,n=e.emitResponse,a=e.shouldSavePayment,o=q(t,a);return Object(i.createElement)(c.SquarePaymentForm,{formId:"square-credit-card",sandbox:h().isSandbox,applicationId:h().applicationId,locationId:h().locationId,inputStyles:h().inputStyles,placeholderCreditCard:"•••• •••• •••• ••••",placeholderExpiration:Object(l.__)("MM / YY","woocommerce-square"),placeholderCVV:Object(l.__)("CSC","woocommerce-square"),postalCode:o.getPostalCode,cardNonceResponseReceived:o.cardNonceResponseReceived,inputEventReceived:o.handleInputReceived,paymentFormLoaded:function(){return o.setLoaded(!0)}},Object(i.createElement)(M,{cardType:o.cardType}),o.isLoaded&&Object(i.createElement)(j,{checkoutFormHandler:o,eventRegistration:r,emitResponse:n}))},N=["RenderedComponent"],k=function(e){var t=e.RenderedComponent,r=o()(e,N);return Object(i.createElement)(t,r)},D={name:"square-credit-card",label:Object(i.createElement)((function(e){var t=e.components.PaymentMethodLabel;return Object(i.createElement)(t,{text:h().title})}),null),content:Object(i.createElement)(k,{RenderedComponent:R}),edit:Object(i.createElement)(k,{RenderedComponent:R}),savedTokenComponent:Object(i.createElement)(k,{RenderedComponent:function(e){var t=e.billing,r=e.eventRegistration,n=e.emitResponse,a=e.token,o=q(t,!1,a);return Object(i.createElement)(c.SquarePaymentForm,{formId:"square-credit-card-saved-card",sandbox:h().isSandbox,applicationId:h().applicationId,locationId:h().locationId,paymentFormLoaded:function(){return o.setLoaded(!0)}},o.isLoaded&&Object(i.createElement)(j,{checkoutFormHandler:o,eventRegistration:r,emitResponse:n}))}}),paymentMethodId:"square_credit_card",ariaLabel:"Square",canMakePayment:function(){return!(!h().applicationId||!h().locationId)},supports:{features:h().supports,showSavedCards:h().showSavedCards,showSaveOption:h().showSaveOption}};Object(n.registerPaymentMethod)(D)}]);
1
+ !function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=30)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.regeneratorRuntime},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=window.React},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t};Object.defineProperty(t,"__esModule",{value:!0});var a=r(n(3));t.Context=a.createContext({applePayState:"loading",formId:"",googlePayState:"loading",masterpassState:"loading",onCreateNonce:function(){},onVerifyBuyer:function(e,t,n){}}),t.default=t.Context},function(e,t){function n(e,t,n,r,a,o,i){try{var u=e[o](i),l=u.value}catch(e){return void n(e)}u.done?t(l):Promise.resolve(l).then(r,a)}e.exports=function(e){return function(){var t=this,r=arguments;return new Promise((function(a,o){var i=e.apply(t,r);function u(e){n(i,a,o,u,l,"next",e)}function l(e){n(i,a,o,u,l,"throw",e)}u(void 0)}))}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){var r=n(25),a=n(26),o=n(27),i=n(29);e.exports=function(e,t){return r(e)||a(e,t)||o(e,t)||i()},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}Object.defineProperty(t,"__esModule",{value:!0});var a=n(8);r(n(15)),r(n(4)),r(n(16)),r(n(17)),r(n(18)),r(n(19)),r(n(20)),r(n(21)),r(n(22)),r(n(23)),r(n(24)),r(n(8)),t.default=a.SquarePaymentForm},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(14)),u=a(n(4));t.SquarePaymentForm=function(e){var t=o.useState("loading"),n=t[0],r=t[1],a=o.useState("loading"),l=a[0],s=a[1],c=o.useState("loading"),d=c[0],f=c[1],p=o.useState(""),m=p[0],v=p[1],y=o.useState(!1),b=y[0],g=y[1],h=o.useState(void 0),_=h[0],O=h[1],C=o.useState(!1),S=C[0],x=C[1],P=i.default((function(t,n,r,a,o,i){!t&&e.createVerificationDetails?_&&_.verifyBuyer(n,e.createVerificationDetails(),(function(t,u){e.cardNonceResponseReceived(t?[t]:null,n,r,u?u.token:void 0,a,o,i)})):e.cardNonceResponseReceived(t,n,r,"",a,o,i)}));function E(t){var n=Object.keys(t);n.includes("masterpass")&&f(!0===t.masterpass?"ready":"unavailable"),n.includes("applePay")&&r(!0===t.applePay?"ready":"unavailable"),n.includes("googlePay")&&s(!0===t.googlePay?"ready":"unavailable"),e.methodsSupported&&e.methodsSupported(t)}var j=function(){x(!0),e.paymentFormLoaded&&e.paymentFormLoaded()};if(o.useEffect((function(){S&&_&&(_.recalculateSize(),e.postalCode&&_.setPostalCode(e.postalCode()),e.focusField&&_.focus(e.focusField()))}),[S,_]),o.useEffect((function(){!function(t,n){if(document.getElementById("sq-payment-form-script")&&"function"==typeof SqPaymentForm)t&&t();else{var r=document.createElement("script");r.id="sq-payment-form-script",e.sandbox?r.src="https://js.squareupsandbox.com/v2/paymentform":r.src="https://js.squareup.com/v2/paymentform",r.onload=function(){t&&t()},r.onerror=function(){n&&n()},document.body.appendChild(r)}}((function(){return g(!0)}),(function(){return v("Unable to load Square payment library")}))}),[]),o.useEffect((function(){return function(){if(!(!b||_||m.length>0))try{var t=new SqPaymentForm(function(e){var t={apiWrapper:e.apiWrapper,applicationId:e.applicationId,autoBuild:!1,callbacks:{cardNonceResponseReceived:e.cardNonceResponseReceived?P:null,createPaymentRequest:e.createPaymentRequest,inputEventReceived:e.inputEventReceived,methodsSupported:E,paymentFormLoaded:j,shippingContactChanged:e.shippingContactChanged,shippingOptionChanged:e.shippingOptionChanged,unsupportedBrowserDetected:e.unsupportedBrowserDetected},locationId:e.locationId};return document.getElementById(e.formId+"-sq-card")?t.card={elementId:e.formId+"-sq-card",inputStyle:e.inputStyles&&e.inputStyles[0]}:document.getElementById(e.formId+"-sq-gift-card")?(t.giftCard={elementId:e.formId+"-sq-gift-card",placeholder:e.placeholderGiftCard||"• • • • • • • • • • • • • • • •"},t.inputClass=e.inputClass||"sq-input",t.inputStyles=e.inputStyles):(t.inputClass=e.inputClass||"sq-input",t.inputStyles=e.inputStyles,document.getElementById(e.formId+"-sq-apple-pay")&&(t.applePay={elementId:e.formId+"-sq-apple-pay"}),document.getElementById(e.formId+"-sq-google-pay")&&(t.googlePay={elementId:e.formId+"-sq-google-pay"}),document.getElementById(e.formId+"-sq-masterpass")&&(t.masterpass={elementId:e.formId+"-sq-masterpass"}),document.getElementById(e.formId+"-sq-card-number")&&(t.cardNumber={elementId:e.formId+"-sq-card-number",placeholder:e.placeholderCreditCard||"• • • • • • • • • • • • • • • •"}),document.getElementById(e.formId+"-sq-cvv")&&(t.cvv={elementId:e.formId+"-sq-cvv",placeholder:e.placeholderCVV||"CVV "}),document.getElementById(e.formId+"-sq-postal-code")?t.postalCode={elementId:e.formId+"-sq-postal-code",placeholder:e.placeholderPostal||"12345"}:t.postalCode=!1,document.getElementById(e.formId+"-sq-expiration-date")&&(t.expirationDate={elementId:e.formId+"-sq-expiration-date",placeholder:e.placeholderExpiration||"MM/YY"})),t}(e));t.build(),O(t)}catch(e){var n=e.message||"Unable to build Square payment form";v(n)}}(),function(){_&&(_.destroy(),O(void 0))}}),[b]),o.useEffect((function(){if(_&&"ready"===d){var t=document.getElementById(e.formId+"-sq-masterpass");if(t){var n=_.masterpassImageUrl();t.style.display="inline-block",t.style.backgroundImage="url("+n+")"}}}),[_,d]),m)return o.default.createElement("div",{className:"sq-payment-form"},o.default.createElement("div",{className:"sq-error-message"},m));var w={applePayState:n,formId:e.formId,googlePayState:l,masterpassState:d,onCreateNonce:function(){_&&_.requestCardNonce()},onVerifyBuyer:function(e,t,n){_&&_.verifyBuyer(e,t,n)}};return o.default.createElement(u.default.Provider,{value:w},o.default.createElement("div",{id:e.formId,className:"sq-payment-form"},e.children))},t.SquarePaymentForm.defaultProps={apiWrapper:"reactjs/0.7.2",formId:"sq-payment-form",inputStyles:[{_mozOsxFontSmoothing:"grayscale",_webkitFontSmoothing:"antialiased",backgroundColor:"transparent",color:"#373F4A",fontFamily:"Helvetica Neue",fontSize:"16px",lineHeight:"24px",padding:"16px",placeholderColor:"#CCC"}],sandbox:!1}},function(e,t){e.exports=window.wc.wcBlocksRegistry},function(e,t,n){var r=n(12);e.exports=function(e,t){if(null==e)return{};var n,a,o=r(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a<i.length;a++)n=i[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=window.wc.wcSettings},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=window.wp.i18n},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(3);t.default=function(e){var t=r.useRef(e);return r.useLayoutEffect((function(){t.current=e}),[e]),r.useCallback((function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return t.current.apply(t,e)}),[])}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.ApplePayButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-apple-pay",className:"sq-apple-pay",style:{display:"ready"===t.applePayState?"block":"none"}}),"loading"===t.applePayState&&e.loadingView,"unavailable"===t.applePayState&&e.unavailableView)}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.CreditCardCVVInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-cvv"}))},t.CreditCardCVVInput.defaultProps={label:"CVV"}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.CreditCardExpirationDateInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-expiration-date"}))},t.CreditCardExpirationDateInput.defaultProps={label:"Expiration"}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.CreditCardNumberInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-card-number"}))},t.CreditCardNumberInput.defaultProps={label:"Credit Card"}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.CreditCardPostalCodeInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-postal-code"}))},t.CreditCardPostalCodeInput.defaultProps={label:"Postal"}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.CreditCardSubmitButton=function(e){var t=o.useContext(i.default);return o.default.createElement("button",{className:"sq-creditcard",onClick:t.onCreateNonce},e.children?e.children:"Pay")}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.GiftCardInput=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,e.label&&o.default.createElement("span",{className:"sq-label"},e.label),o.default.createElement("div",{id:t.formId+"-sq-gift-card"}))},t.GiftCardInput.defaultProps={label:"Gift Card"}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.GooglePayButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-google-pay",className:"sq-google-pay",style:{display:"ready"===t.googlePayState?"block":"none"}}),"loading"===t.googlePayState&&e.loadingView,"unavailable"===t.googlePayState&&e.unavailableView)}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.MasterpassButton=function(e){var t=o.useContext(i.default);return o.default.createElement("div",null,o.default.createElement("button",{id:t.formId+"-sq-masterpass",className:"sq-masterpass",style:{display:"ready"===t.masterpassState?"block":"none"}}),"loading"===t.masterpassState&&e.loadingView,"unavailable"===t.masterpassState&&e.unavailableView)}},function(e,t,n){"use strict";var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(3)),i=a(n(4));t.SimpleCard=function(){var e=o.useContext(i.default);return o.default.createElement("div",{id:e.formId+"-sq-card"})}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],_n=!0,i=!1;try{for(n=n.call(e);!(_n=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);_n=!0);}catch(e){i=!0,a=e}finally{try{_n||null==n.return||n.return()}finally{if(i)throw a}}return o}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){var r=n(28);e.exports=function(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){"use strict";n.r(t);var r=n(9),a=n(10),o=n.n(a),i=n(0),u=(n(13),n(7)),l=n(2),s=n.n(l),c=n(5),d=n.n(c),f=n(1),p=n.n(f),m=n(11);function v(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return y(e,void 0);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?y(e,void 0):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,a=function(){};return{s:a,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,u=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){u=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(u)throw o}}}}function y(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var b=null,g=function(){if(null!==b)return b;var e=Object(m.getSetting)("square_credit_card_data",null);if(!e)throw new Error("Square initialization data is not available");return b={title:e.title||"",applicationId:e.application_id||"",locationId:e.location_id||"",isSandbox:e.is_sandbox||!1,is3dsEnabled:e.is_3ds_enabled||!1,inputStyles:e.input_styles||[],availableCardTypes:e.available_card_types||{},loggingEnabled:e.logging_enabled||!1,generalError:e.general_error||"",showSavedCards:e.show_saved_cards||!1,showSaveOption:e.show_save_option||!1,supports:e.supports||{}}},h=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{logs:[],notices:[]},n=!1;if(e){var r=["none","cardNumber","expirationDate","cvv","postalCode"];e.length>=1&&e.sort((function(e,t){return r.indexOf(e.field)-r.indexOf(t.field)}));var a,o=v(e);try{for(o.s();!(a=o.n()).done;){var i=a.value;"UNSUPPORTED_CARD_BRAND"===i.type||"VALIDATION_ERROR"===i.type?(t.notices.push(i.message.replace(/CVV/,"CSC")),n=!0):O(i,t)}}catch(e){o.e(e)}finally{o.f()}}n||t.notices.push(g().generalError)},_=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"notice";g().loggingEnabled&&("error"===t?console.error(e):console.log(e))},O=function(e,t){g().loggingEnabled&&t&&t.logs.push(e)};function C(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function S(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?C(Object(n),!0).forEach((function(t){s()(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):C(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var x=Object(i.createContext)(!1),P=function(e){var t=e.checkoutFormHandler,n=e.eventRegistration,r=e.emitResponse,a=Object(i.useContext)(x),o=n.onPaymentProcessing,u=n.onCheckoutAfterProcessingWithError,l=n.onCheckoutAfterProcessingWithSuccess;return function(e,t,n,r,a,o){var u=Object(i.useRef)(n);Object(i.useEffect)((function(){u.current=n}),[n]),Object(i.useEffect)((function(){return e(function(){var e=d()(p.a.mark((function e(){var n,i,l,s,c,d,f,m;return p.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return l={type:t.responseTypes.SUCCESS},s={nonce:"",notices:[],logs:[]},e.next=4,a(u.current.card);case 4:if(c=e.sent,d=S(S({},s),{},{nonce:c.token}),null!=c&&null!==(n=c.details)&&void 0!==n&&n.card&&null!=c&&null!==(i=c.details)&&void 0!==i&&i.billing&&(d.cardData=S(S({},c.details.card),c.details.billing)),f=d.token||d.nonce,!g().is3dsEnabled||!f){e.next=15;break}return e.next=11,o(u.current.payments,f);case 11:m=e.sent,d.verificationToken=m.verificationToken||"",d.logs=d.logs.concat(m.log||[]),d.errors=d.notices.concat(m.errors||[]);case 15:return f||d.logs.length>0?l.meta={paymentMethodData:r(d)}:d.notices.length>0&&(l.type=t.responseTypes.ERROR,l.message=d.notices),e.abrupt("return",l);case 17:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}())}),[e,t.responseTypes.SUCCESS,t.responseTypes.ERROR,a,o,r])}(o,r,a,t.getPaymentMethodData,t.createNonce,t.verifyBuyer),function(e,t,n){Object(i.useEffect)((function(){var r=function(e){var t={type:n.responseTypes.SUCCESS},r=e.processingResponse,a=r.paymentStatus,o=r.paymentDetails;return a===n.responseTypes.ERROR&&o.checkoutNotices&&(t={type:n.responseTypes.ERROR,message:JSON.parse(o.checkoutNotices),messageContext:n.noticeContexts.PAYMENTS,retry:!0}),t},a=e(r),o=t(r);return function(){a(),o()}}),[e,t,n.noticeContexts.PAYMENTS,n.responseTypes.ERROR,n.responseTypes.SUCCESS])}(u,l,r),null},E=n(6),j=n.n(E),w=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=Object(i.useState)(!1),a=j()(r,2),o=a[0],u=a[1],l=Object(i.useState)(""),c=j()(l,2),f=c[0],m=c[1],v=Object(i.useRef)(null),y=Object(i.useRef)(null),b=Object(i.useMemo)((function(){var r=t&&!n?"STORE":"CHARGE",a={billingContact:{familyName:e.billingData.last_name||"",givenName:e.billingData.first_name||"",email:e.billingData.email||"",country:e.billingData.country||"",region:e.billingData.state||"",city:e.billingData.city||"",postalCode:e.billingData.postcode||"",phone:e.billingData.phone||"",addressLines:[e.billingData.address_1||"",e.billingData.address_2||""]},intent:r};return"CHARGE"===r&&(a.amount=(e.cartTotal.value/100).toString(),a.currencyCode=e.currency.code),a}),[e.billingData,e.cartTotal.value,e.currency.code,t,n]),C=Object(i.useCallback)((function(e){var r,a,o,i=e.cardData,u=void 0===i?{}:i,l=e.nonce,c=e.verificationToken,d=e.notices,p=e.logs;return o={},s()(o,"wc-".concat("square-credit-card","-card-type"),f||""),s()(o,"wc-".concat("square-credit-card","-last-four"),(null==u?void 0:u.last4)||""),s()(o,"wc-".concat("square-credit-card","-exp-month"),(null==u||null===(r=u.expMonth)||void 0===r?void 0:r.toString())||""),s()(o,"wc-".concat("square-credit-card","-exp-year"),(null==u||null===(a=u.expYear)||void 0===a?void 0:a.toString())||""),s()(o,"wc-".concat("square-credit-card","-payment-postcode"),(null==u?void 0:u.postalCode)||""),s()(o,"wc-".concat("square-credit-card","-payment-nonce"),l||""),s()(o,"wc-".concat("square-credit-card","-payment-token"),n||""),s()(o,"wc-".concat("square-credit-card","-buyer-verification-token"),c||""),s()(o,"wc-".concat("square-credit-card","-tokenize-payment-method"),t||!1),s()(o,"log-data",p.length>0?JSON.stringify(p):""),s()(o,"checkout-notices",d.length>0?JSON.stringify(d):""),o}),[f,t,n]),S=function(e,t,n){var r={notices:[],logs:[]};e?h(e,r):t?(O(n,r),_("Card data received"),_(n),r.cardData=n,r.nonce=t):(O("Nonce is missing from the Square response",r),_("Nonce is missing from the Square response","error"),h([],r)),v.current&&v.current(r)},x=Object(i.useCallback)(function(){var e=d()(p.a.mark((function e(t){return p.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n){e.next=4;break}return e.next=3,t.tokenize();case 3:return e.abrupt("return",e.sent);case 4:return e.abrupt("return",n);case 5:case"end":return e.stop()}}),e)})));return function(_x){return e.apply(this,arguments)}}(),[n]),P=Object(i.useCallback)(function(){var e=d()(p.a.mark((function e(t,n){var r;return p.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,t.verifyBuyer(n,b);case 3:return r=e.sent,e.abrupt("return",E(r));case 7:e.prev=7,e.t0=e.catch(0),h([e.t0]);case 10:return e.abrupt("return",!1);case 11:case"end":return e.stop()}}),e,null,[[0,7]])})));return function(t,n){return e.apply(this,arguments)}}(),[b,E]),E=Object(i.useCallback)((function(e){var t={notices:[],logs:[]};return e&&e.token?t.verificationToken=e.token:(O("Verification token is missing from the Square response",t),_("Verification token is missing from the Square response","error"),h([],t)),t}),[y]),w=Object(i.useCallback)((function(e){if("cardBrandChanged"===e.eventType){var t=e.cardBrand,n="plain";null!==t&&"unknown"!==t||(n=""),null!==g().availableCardTypes[t]&&(n=g().availableCardTypes[t]),_("Card brand changed to ".concat(t)),m(n)}}),[]),I=Object(i.useCallback)((function(){return e.billingData.postcode||""}),[e.billingData.postcode]);return{cardNonceResponseReceived:S,handleInputReceived:w,isLoaded:o,setLoaded:u,getPostalCode:I,cardType:f,createNonce:x,verifyBuyer:P,getPaymentMethodData:C}},I=function(e){var t=e.children,n=e.defaults.postalCode,r=void 0===n?"":n,a=Object(i.useState)(!1),o=j()(a,2),u=o[0],l=o[1],s=Object(i.useState)(!1),c=j()(s,2),f=c[0],m=c[1],v=g(),y=v.applicationId,b=v.locationId;return Object(i.useEffect)((function(){!u&&window.Square&&l(window.Square.payments(y,b))}),[u]),Object(i.useEffect)((function(){u&&!f&&function(){var e=d()(p.a.mark((function e(){var t;return p.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u.card({postalCode:r});case 2:t=e.sent,m(t);case 4:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}()()}),[u]),u?Object(i.createElement)(x.Provider,{value:{payments:u,card:f}},t):null},q=function(){var e=Object(i.useContext)(x).card,t=Object(i.useRef)(!1);return Object(i.useEffect)((function(){e&&function(){var n=d()(p.a.mark((function n(){return p.a.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:e.attach(t.current);case 1:case"end":return n.stop()}}),n)})));return function(){return n.apply(this,arguments)}}()()}),[e]),Object(i.createElement)("div",{ref:t})},M=function(e){var t=e.billing,n=e.eventRegistration,r=e.emitResponse,a=e.shouldSavePayment,o=w(t,a);return Object(i.createElement)(I,{defaults:{postalCode:o.getPostalCode()}},Object(i.createElement)(q,null),Object(i.createElement)(P,{checkoutFormHandler:o,eventRegistration:n,emitResponse:r}))},R=["RenderedComponent"],k=function(e){var t=e.RenderedComponent,n=o()(e,R);return Object(i.createElement)(t,n)},D={name:"square-credit-card",label:Object(i.createElement)((function(e){var t=e.components.PaymentMethodLabel;return Object(i.createElement)(t,{text:g().title})}),null),content:Object(i.createElement)(k,{RenderedComponent:M}),edit:Object(i.createElement)(k,{RenderedComponent:M}),savedTokenComponent:Object(i.createElement)(k,{RenderedComponent:function(e){var t=e.billing,n=e.eventRegistration,r=e.emitResponse,a=e.token,o=w(t,!1,a);return Object(i.createElement)(u.SquarePaymentForm,{formId:"square-credit-card-saved-card",sandbox:g().isSandbox,applicationId:g().applicationId,locationId:g().locationId,paymentFormLoaded:function(){return o.setLoaded(!0)}},o.isLoaded&&Object(i.createElement)(P,{checkoutFormHandler:o,eventRegistration:n,emitResponse:r}))}}),paymentMethodId:"square_credit_card",ariaLabel:"Square",canMakePayment:function(){return!(!g().applicationId||!g().locationId)},supports:{features:g().supports,showSavedCards:g().showSavedCards,showSaveOption:g().showSaveOption}};Object(r.registerPaymentMethod)(D)}]);
changelog.txt ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *** WooCommerce Square Changelog ***
2
+
3
+ = 3.0.0 - 2022-05-04 =
4
+ * New - Upgrade the payment form on checkout to use the latest Square Web Payments SDK. PR#668
5
+ * Fix - Compatibility issues with WordPress 6.1.0. PR#715
6
+ * Fix - Sync issues caused by product variations having an empty SKU and incorrectly being set to the variable product (parent product) SKU value. PR#764
7
+ * Update - Remove admin notice warning of v3.0.0 release. PR#744
8
+ * Dev - Product importing is now handled by Action Scheduler. PR#698
9
+ * Dev - Syncing is now handled by Action Scheduler. PR#699
10
+ * Dev - Manual Sync is now handled by Action Scheduler. PR#710
11
+ * Dev - Upgrade Action Scheduler to 3.4.0. PR#762
12
+ * Dev - Updated Square Connect to Square SDK v 15.0.0. PR#673 PR#670 PR#668 PR#664 PR#659 PR#657
13
+ * Dev - Remove SkyVerge framework. PR#690 PR#689 PR#688 PR#687 PR#684 PR#683 PR#681 PR#678
14
+
15
+ = 2.9.1 - 2022-03-17 =
16
+ * Fix - Fatal error while deactivating WooCommerce before WooCommerce Square.
17
+
18
+ = 2.9.0 - 2022-02-17 =
19
+ * New - Added admin notice about v3 major update. PR#707
20
+ * Fix - Trim spaces from postal code at prefix and suffix positions. PR#654
21
+
22
+ = 2.8.0 - 2022-01-24 =
23
+ * New - Add support for Square stores located in Spain. PR#704
24
+
25
+ = 2.7.0 - 2021-11-09 =
26
+ * New - `wc_square_beta_country_support_spain` filter to add Spain as a supported country. PR#663
27
+ * Fix - Visibility of digital wallet buttons based on account & privacy settings. PR#652
28
+
29
+ = 2.6.0 - 2021-09-29 =
30
+ * New - Add support for Square stores located in France. PR#650
31
+ * Fix - PHP warning when trying to load the Square digital wallet (Apple/Google Pay buttons) on a product page that isn't available for purchase. PR#640
32
+
33
+ = 2.5.3 - 2021-07-23 =
34
+ * Fix - Failed orders with error "Square Payment Failed (Status code VALUE_TOO_LOW)" caused by incorrect line item calculations on orders with discounts/coupons (introduced in 2.5.2). PR#635
35
+
36
+ = 2.5.2 - 2021-07-21 =
37
+ * Fix - Product and inventory data not being synced due to duplicate/orphaned product metadata in database. PR#625
38
+ * Fix - Bypass SSL verification when checking background job processing eligibility. PR#624
39
+ * Fix - Correctly apply taxes in the Order API request and report accurate percentages. PR#559
40
+
41
+ = 2.5.1 - 2021-05-18 =
42
+ * Fix - Pay for Order and Add Payment Method forms sometimes not working when choosing another payment method other than Square. PR#618
43
+
44
+ = 2.5.0 - 2021-05-13 =
45
+ * New - Add support for WooCommerce Checkout blocks. PR#604
46
+ * New - Add support for Square stores located in Ireland. PR#609
47
+ * Fix - Improve manual sync performance and reduce stream timeout responses from Square on stores with large catalogs. PR#612
48
+
49
+ = 2.4.1 - 2021-03-30 =
50
+ * Fix - Variable products are now properly importing from Square on newer versions of WooCommerce. PR#605
51
+
52
+ = 2.4.0 - 2021-03-23 =
53
+ * Fix - Update jQuery 3 deprecated functions. PR#560
54
+ * Fix - Don't display digital wallet buttons when the cart contains a subscription product as Square does not yet support tokenization through digital wallets. PR#597
55
+ * Dev - Replace CoffeeScript with plain JS. PR#560
56
+
57
+ = 2.3.4 - 2021-02-11 =
58
+ * Fix - Handle exceptions when loading digital wallet buttons on product pages with no stock or other serviceable issues. PR#591
59
+
60
+ = 2.3.3 - 2021-02-09 =
61
+ * Fix - Uncaught PHP error when attempting to setup Apple Pay and Square is not properly connected (i.e. no valid access token found). PR#587
62
+ * Fix - Improve error logging when the request to verify the store's domain with Square/Apple Pay fails. PR#587
63
+ * Fix - Allow variable products to be previewed when Square is active. PR#554
64
+
65
+ = 2.3.2 - 2021-02-04 =
66
+ * Fix - PHP error on the My Account > Payment Methods page when saving a new card. PR#585
67
+
68
+ = 2.3.1 - 2021-02-03 =
69
+ * Fix - Add the correct variation to the cart when purchasing with Apple Pay and Google Pay from the product page. PR#581
70
+
71
+ = 2.3.0 - 2021-02-02 =
72
+ * Feature - Apple Pay and Google Pay support (US, UK and CA stores only). PR#547
73
+ * Fix - Duplicate `idempotency_key` issues caused by order IDs being re-used on the same store URL (i.e. after restoring from a backup). PR#563
74
+ * Fix - Don't import item variations from Square that are not available at your store's business location. PR#562
75
+ * Fix - Restore stock in Square when processing partial refunds (previously was only restoring stock for full refunds). PR#565
76
+ * Fix - Only restore stock if the "Restock refunded items" option is checked when refunding an order. PR#565
77
+ * Fix - Fatal errors during the sync and import process caused by unexpected/invalid Square API responses. PR#500
78
+ * Fix - Sends only one sync complete email per update to products that are synced with Square. PR#552
79
+ * Fix - Allow products with large numbers of categories (600+) to sync to Square when WooCommerce is SOR. PR#568
80
+ * Fix - Database related errors with creating the Square customer's table when first installing Square. PR#558
81
+ * Fix - Allow variable products with valid variations to import when variations with missing skus are present. PR#573
82
+ * Tweak - Update the Customer Profile setting description to make it clear that this setting enables tokenization. PR#576
83
+
84
+ = 2.2.5 - 2020-11-24 =
85
+ * Fix - Correctly saves inventory sync time when sync fails so items are re-synced on next attempt. PR#448
86
+ * Fix - Fixes warnings introduced with PHP 8. PR#533
87
+ * Fix - Corrects the plugin support URL. PR#539
88
+ * Fix - Allows imports containing products with variable pricing to complete successfully. PR#540
89
+ * Tweak - Updates assets to reflect WooCommerce color change. PR#544
90
+
91
+ = 2.2.4 - 2020-10-30 =
92
+ * Fix - Prevents logging anything if logging is disabled. PR#493
93
+ * Fix - Fixes a bug where products are imported even when it is not available at the store's location. PR#537
94
+
95
+ = 2.2.3 - 2020-10-23 =
96
+ * Fix - Display the correct stock quantity amount on all variations when product data is sent to Square. PR#503
97
+ * Fix - Avoid IDEMPOTENCY_KEY_REUSED API errors when syncing product data from WooCommerce to Square by using a more unique API request key. PR#528
98
+ * Fix - Added customer_id to Orders API to link Customers & Transactions on Square Dashboard and Transactions CSV Export. PR#527
99
+ * Fix - Issues with the postal code not matching WooCommerce data while saving cards. PR#501
100
+ * Fix - Prevents the "Send product data to Square" checkbox from being enabled when products and variations contain empty or duplicate SKUs. PR#525
101
+ * Fix - Issues that caused the Square Payment Form to be unclickable on the checkout page. PR#530
102
+ * Fix - Compatibility issues with the Square Payment form and conditional payment gateway extensions. PR#530
103
+
104
+ = 2.2.2 - 2020-09-15 =
105
+ * Fix - Don't import a new copy of each product image from Square when updating products during the import process. PR#513
106
+
107
+ = 2.2.1 - 2020-09-11 =
108
+ * New - Make the "Update existing products" part of the new import process optional by adding a new checkbox on Import Products modal. PR#508
109
+ * Fix - Stop the import process from getting stuck in a loop when reaching the time limit. PR#511
110
+ * Fix - Don't import/update categories from Square that are attached to products that cannot be found in WooCommerce. PR#511
111
+ * Fix - "idempotency_key must not be greater than 45 length" errors returned by some payment requests on stores using custom order number plugins. PR#507
112
+
113
+ = 2.2.0 - 2020-08-31 =
114
+ * Feature - Import new product variations from square to existing products in WooCommerce. PR#475
115
+ * Feature - Variations that are removed from Square will now be removed from products in WooCommerce during import. PR#475
116
+ * Feature - Upgrade to the Square Payments and Refunds API. PR#408
117
+ * Feature - New orders can be refunded up to one year after payment (up from 120 days). PR#408
118
+ * Fix - Only import products from Square that have non-empty SKUs. PR#475
119
+ * Fix - Empty product categories imported from Square into WooCommerce. PR#475
120
+ * Fix - Assign existing products to new categories imported from Square. PR#475
121
+ * Fix - Prevents loading of Square Assets on all pages except My Account -> Payment Methods & Checkout. PR#469
122
+ * Fix - Square Product Import & Product Manual Sync not triggering on mobile browsers. PR#472
123
+ * Fix - 3D Secure Verification Token is missing, Intent mismatch and other checkout errors related to SCA for merchants outside of the EU. PR#471
124
+ * Fix - Updated some of our documentation and support links in admin notices so they no longer redirect to an old URL or a 404 page. PR#474
125
+ * Fix - Use pagination to fetch inventory counts from Square. PR#478
126
+ * Fix - Display WooCommerce checkout validation errors along with Square payment form errors. PR#476
127
+ * Fix - Switching between sandbox and production environments will now show correct business locations. PR#462
128
+ * Fix - Don't wipe a customer's saved cards on when we receive an API error. PR#460
129
+ * Fix - Exclude draft and pending products from syncing from WooCommerce to Square. PR#484
130
+ * Fix - DevTools errors caused by missing minified JS files.
131
+ * Fix - PHP errors when syncing large amounts of products (`get_data() on null` and `getCursor() on a string`). PR#497
132
+
133
+ = 2.1.6 - 2020-07-15 =
134
+ * Fix - Make the "Sync Now" button disabled when no business location is set in Square settings.
135
+ * Fix - Enable checking/unchecking the Manage Stock setting for all variations.
136
+ * Fix - Refunding an order paid with another payment gateway will no longer sync inventory with Square when "Do not sync product data" is selected.
137
+ * Fix - Imported variation products that are out-of-stock will no longer show on the shop page when "Hide out of stock items from the catalog" is selected.
138
+ * Fix - Product images will now sync when Square is in Sandbox mode.
139
+ * Fix - Damaged stock adjustments will now sync properly to WooCommerce when multiple stock adjustments are made.
140
+ * Fix - Improve performance when manually syncing large amount of stock adjustments from Square (some inventory updates were missing).
141
+ * Fix - Quick editing products no longer sets incorrect stock quantities or disables syncing.
142
+ * Fix - Existing customer that have been removed from the connected Square account, or can't be found will now be able to save a new card on the checkout.
143
+ * Fix - When the System of Record is set to WooCommerce, product images will now properly sync to Square.
144
+ * Tweak - Use CSC consistently in all error messages when referring to the Card Security Code.
145
+ * Tweak - Change to using WordPress core methods to import/sync images from Square.
146
+
147
+ = 2.1.5 - 2020-05-15 =
148
+ * Fix - Fatal errors caused by incorrectly fetching locations before plugin init.
149
+ * Fix - WordPress database error when creating the Square Customers table on servers using utf8mb4.
150
+
151
+ = 2.1.4 - 2020-05-05 =
152
+ * Fix - Make sure that Square credit card fields are editable after checkout form refresh.
153
+
154
+ = 2.1.3 - 2020-04-30 =
155
+ * Fix - Persistent caching of locations to prevent unnecessary refetching and rate limiting.
156
+
157
+ = 2.1.2 - 2020-04-29 =
158
+ * Fix - INTENT_MISMATCH errors when guest customers save a card and registration is disabled.
159
+ * Fix - Improve checkout compatibility with password managers such as 1Password. This also avoids payment for reload on address change.
160
+ * Fix - Pass valid address values even if checkout fields are not present.
161
+ * Tweak - Sandbox mode can be turned on in the settings, no more need for setting the constant.
162
+ * Tweak - Change location URL to refer to our docs.
163
+
164
+ = 2.1.1 - 2020-03-23 =
165
+ * Fix - Inventory/Stock updates as a result of checkout via PayPal Standard does not reflect on the Square item.
166
+ * Fix - Error when trying to save an external product with the modified 'sync with square' value.
167
+ * Fix - Move product check on a possibly invalid product out of the try block avoiding potential further errors.
168
+
169
+ = 2.1.0 - 2020-02-11 =
170
+ * Feature - Add support for SCA (3D Secure 2)
171
+ * Fix - Minor fixes to the Sync completed emails
172
+ * Tweak - Add email notifications when connection issues are detected
173
+ * Fix - Category sync when WooCommerce is the System of Record and there have been changes in Square
174
+
175
+ = 2.0.8 - 2019-12-09 =
176
+ * Fix - Inventory changes through payments and refunds from other gateways not reflected on Square.
177
+ * Fix - Fatal error on versions of WooCommerce before 4.3.
178
+ * Fix - Sandbox API calls by passing is_sandbox flag to the Gateway API.
179
+ * Fix - Quick edit view when editing a variable product without all variations SKU.
180
+ * Fix - Verify if the product can be synced with Square before enabling sync when bulk/quick updating.
181
+ * Fix - Disable sync for products that should not be synced after a REST API update.
182
+ * Fix - Unable to create products during import.
183
+ * Fix - Product inventory sync issue when WooCommerce is set as the Source of Record.
184
+ * Fix - Inventory not updated when purchased through another gateway.
185
+ * Fix - Category and description data not updated in a sync from Square.
186
+ * Fix - Transactions on multiple stores connected to the same Square account would appear to succeed without actually charging the customer.
187
+ * Fix - When making multiple partial refunds on the same order, only the first one would work.
188
+ * Tweak - Include product ID on failed sync record message.
189
+ * Tweak - Remove notices for refresh token when sandbox is enabled.
190
+ * Tweak - Prevent refreshing a token token when sandbox is enabled.
191
+
192
+ = 2.0.7 - 2019-11-18 =
193
+ * Fix - No longer automatically disconnect on unexpected authorization errors
194
+ * Fix - Bump compatibility for WooCommerce 3.8 and WordPress 5.3
195
+ * Fix - Correct cents rounding that was causing invalid value errors
196
+ * Fix - Fix encrypted token handling
197
+ * Fix - No longer call revoke when disconnecting - just disconnect the site
198
+
199
+ = 2.0.6 - 2019-11-07 =
200
+ * Fix - Access token renewal schedule action duplication.
201
+
202
+ = 2.0.5 - 2019-10-16 =
203
+ * Fix - Access token renewal by adding support for refresh tokens as per the new Square API
204
+ * Fix - Variable pricing import and adding an alert when these type of products are ignored.
205
+ * Fix - Line item discounts and other adjustments being ignored.
206
+ * Tweak - Add a notice when a refresh token is not present to warn users to re-connect their accounts.
207
+ * Feature - Added support for Sandbox accounts.
208
+
209
+ = 2.0.4 - 2019-09-03 =
210
+ * Fix - Add adjustments to Square order in the event of discrepancy with WooCommerce total
211
+
212
+ = 2.0.3 - 2019-08-19 =
213
+ * Tweak - Re-introduce the "inventory sync" toggle to allow syncing product data without affecting inventory
214
+ * Fix - Adjust v1 upgrades to properly toggle inventory sync when not enabled in v1
215
+ * Fix - Ensure product prices are correctly converted to and from cents regardless of the decimal place setting
216
+ * Fix - Don't block the product stock management UI when product sync is disabled
217
+ * Fix - Ensure products that have multiple attributes that aren't used for variations can be synced
218
+ * Misc - Add support for WooCommerce 3.7
219
+
220
+ = 2.0.2 - 2019-08-13 =
221
+ * Tweak – WC 3.7 compatibility.
222
+
223
+ = 2.0.1 - 2019-07-23 =
224
+ * Fix - Don't display the "unsupported" payment processing admin notice for UK-based merchants
225
+
226
+ = 2.0.0 - 2019-07-22 =
227
+ * Feature - Support Square customer profiles for saved payment methods
228
+ * Feature - Customers can label their saved payment methods for easy identification when choosing how to pay
229
+ * Feature - Support enhanced payment form with auto formatting and retina card icons
230
+ * Feature - Show detailed decline messages when possible in place of generic errors
231
+ * Feature - Add support for WooCommerce Subscriptions
232
+ * Feature - Add support for WooCommerce Pre-Orders
233
+ * Feature - Orders with only virtual items can force a charge instead of authorization
234
+ * Feature - Void authorizations from WooCommerce
235
+ * Feature - Itemize Square transactions for improved reporting in Square
236
+ * Feature - Add sync records to notify admins of failed product syncs
237
+ * Feature - Changed "Synced with Square" option while bulk editing products
238
+ * Tweak - Introduce "System of Record" settings to control product data sync
239
+ * Tweak - Remove items from Square locations when deleted in WooCommerce (if WC is the system of record)
240
+ * Tweak - Allow users to hide WooCommerce products if removed from the linked Square location (if Square is the system of record)
241
+ * Tweak - Import images from Square when not set in WooCommerce (if Square is the system of record)
242
+ * Tweak - Remove Square postcode field when a postcode can be used from the checkout form
243
+ * Fix - Ensure connection tokens are refreshed ahead of expiration
244
+ * Fix - Always ensure settings are displayed in multisite
245
+ * Fix - Ensure Square prices update WooCommerce regular price, not sale price
246
+ * Fix - Remove usages of `$HTTP_RAW_POST_DATA`, which is deprecated
247
+ * Fix - Do not allow multiple sync processes to run simultaneously
248
+ * Fix - Avoid submitting duplicate orders with Checkout for WC plugin
249
+ * Misc - Upgrade to Square Connect v2 APIs
250
+ * Misc - Background process product sync for improved scalability
251
+ * Misc - Refactor for other miscellaneous fixes and improved reliability
252
+
253
+ = 1.0.38 - 2019-07-05 =
254
+ * Fix - Re-deploy due to erroneous inclusion of trunk folder
255
+
256
+ = 1.0.37 – 2019-04-16 =
257
+ * Fix – Use correct assets loading scheme.
258
+
259
+ = 1.0.36 – 2019-04-15 =
260
+ * Tweak – WC 3.6 compatibility.
261
+
262
+ = 1.0.35 - 2019-02-01 =
263
+ * Fix - Idempotency key reuse issue when checking out.
264
+
265
+ = 1.0.34 - 2018-11-07 =
266
+ * Update - Fieldset tag to div tag in payment box to prevent unwanted styling.
267
+ * Fix - Provide unique idempotency ID to the order instead of random unique number.
268
+ * Update - WP tested up to version 5.0
269
+
270
+ = 1.0.33 - 2018-09-27 =
271
+ * Update - WC tested up to version 3.5
272
+
273
+ = 1.0.32 - 2018-08-23 =
274
+ * Fix - UK/GB localed does not support Diners/Discover, so do not show these brands on checkout.
275
+
276
+ = 1.0.25 =
277
+ * Public Release!
composer.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "name": "woocommerce/woocommerce-square",
3
- "description": "WooCommerce Square",
4
- "homepage": "https://woocommerce.com/products/woocommerce-square/",
5
- "license": "GPL 3.0",
6
- "minimum-stability": "dev",
7
- "repositories": [
8
- {
9
- "type": "vcs",
10
- "url": "https://github.com/skyverge/wc-plugin-framework"
11
- }
12
- ],
13
- "require": {
14
- "square/connect": "2.20190814.2",
15
- "skyverge/wc-plugin-framework": "5.4.0",
16
- "prospress/action-scheduler" : "2.2.0"
17
- },
18
- "require-dev": {
19
- "woocommerce/woocommerce-sniffs": "0.1.0"
20
- },
21
- "scripts": {
22
- "phpcs": [
23
- "vendor/bin/phpcs"
24
- ]
25
- }
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
i18n/languages/woocommerce-square.pot CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the GNU General Public License v3.0.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WooCommerce Square 2.9.1\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-square\n"
8
- "POT-Creation-Date: 2022-03-17 05:15:45+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
@@ -14,70 +14,70 @@ msgstr ""
14
  "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
15
  "X-Generator: grunt-wp-i18n 1.0.3\n"
16
 
17
- #: includes/AJAX.php:112
18
  msgid "Please mark product as un-synced and save, then synced again."
19
  msgstr ""
20
 
21
- #: includes/AJAX.php:125
22
  #. translators: Placeholders: %1$s = error message, %2$s = help text
23
  msgid "Unable to fetch inventory: %1$s. %2$s"
24
  msgstr ""
25
 
26
- #: includes/AJAX.php:130
27
  #. translators: Placeholders: %s = help text
28
  msgid "Error finding item in Square. %s"
29
  msgstr ""
30
 
31
- #: includes/AJAX.php:148
32
  msgid "Could not start import. Please try again."
33
  msgstr ""
34
 
35
- #: includes/AJAX.php:151
36
  msgid ""
37
  "Your products are being imported in the background! This may take some time "
38
  "to complete."
39
  msgstr ""
40
 
41
- #: includes/AJAX.php:197
42
  msgid "Could not delete records."
43
  msgstr ""
44
 
45
- #: includes/AJAX.php:205
46
  msgid "Could not delete record."
47
  msgstr ""
48
 
49
- #: includes/AJAX.php:215
50
  msgid "Could not resolve record."
51
  msgstr ""
52
 
53
- #: includes/AJAX.php:227
54
  msgid "Could not unsync product."
55
  msgstr ""
56
 
57
- #: includes/AJAX.php:239
58
  #. translators: Placeholder: %s - error message
59
  msgid "An error occurred. %s"
60
  msgstr ""
61
 
62
- #: includes/AJAX.php:284
63
  #. translators: Placeholder: %s - sync job ID
64
  msgid "No sync job in progress found %s"
65
  msgstr ""
66
 
67
- #: includes/AJAX.php:322
68
  msgid "Stock must be fetched from Square before editing stock quantity"
69
  msgstr ""
70
 
71
- #: includes/Admin/Privacy.php:45 includes/Admin/Settings_Page.php:55
72
- #: includes/Gateway.php:80 includes/Settings.php:223 includes/Settings.php:757
73
  msgid "Square"
74
  msgstr ""
75
 
76
- #: includes/Admin/Privacy.php:47
77
  msgid "WooCommerce Square Customer Data"
78
  msgstr ""
79
 
80
- #: includes/Admin/Privacy.php:61
81
  #. translators: Placeholder: %1$s - <a> tag, %2$s - </a> tag
82
  msgid ""
83
  "By using this extension, you may be storing personal data or sharing data "
@@ -85,27 +85,27 @@ msgid ""
85
  "what you may want to include in your privacy policy.%2$s"
86
  msgstr ""
87
 
88
- #: includes/Admin/Privacy.php:93
89
  msgid "Square User Data Erased."
90
  msgstr ""
91
 
92
- #: includes/Admin/Settings_Page.php:145
93
  msgid "Settings"
94
  msgstr ""
95
 
96
- #: includes/Admin/Settings_Page.php:146 includes/Admin/Sync_Page.php:50
97
  msgid "Update"
98
  msgstr ""
99
 
100
- #: includes/Admin/Settings_Page.php:173
101
  msgid "Import Products From Square"
102
  msgstr ""
103
 
104
- #: includes/Admin/Settings_Page.php:175 includes/Admin/Sync_Page.php:359
105
  msgid "Close modal window"
106
  msgstr ""
107
 
108
- #: includes/Admin/Settings_Page.php:180
109
  #. translators: Placeholders: %1$s - <strong>, %2%s - </strong>
110
  msgid ""
111
  "You are about to import all new products, variations and categories from "
@@ -114,11 +114,11 @@ msgid ""
114
  "imports, these will be ignored in the import."
115
  msgstr ""
116
 
117
- #: includes/Admin/Settings_Page.php:182
118
  msgid "Do you wish to import existing product updates from Square?"
119
  msgstr ""
120
 
121
- #: includes/Admin/Settings_Page.php:184
122
  #. translators: Placeholders: %1$s - <a> tag linking to WooCommerce Square
123
  #. docs, %2%s - closing </a> tag
124
  msgid ""
@@ -126,26 +126,26 @@ msgid ""
126
  "information from Square. %1$sView Documentation%2$s."
127
  msgstr ""
128
 
129
- #: includes/Admin/Settings_Page.php:185
130
  msgid "Update existing products during import."
131
  msgstr ""
132
 
133
- #: includes/Admin/Settings_Page.php:189 includes/Admin/Sync_Page.php:393
134
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:133
135
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:66
136
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:227
137
  msgid "Cancel"
138
  msgstr ""
139
 
140
- #: includes/Admin/Settings_Page.php:190 includes/Settings.php:244
141
  msgid "Import Products"
142
  msgstr ""
143
 
144
- #: includes/Admin/Sync_Page.php:54
145
  msgid "Sync records"
146
  msgstr ""
147
 
148
- #: includes/Admin/Sync_Page.php:80
149
  #. translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s,
150
  #. $4%s - closing </strong> HTML tag
151
  msgid ""
@@ -154,7 +154,7 @@ msgid ""
154
  "description, category, inventory%4$s."
155
  msgstr ""
156
 
157
- #: includes/Admin/Sync_Page.php:94
158
  #. translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing
159
  #. </strong> HTML tag
160
  msgid ""
@@ -162,7 +162,7 @@ msgid ""
162
  "set in WooCommerce."
163
  msgstr ""
164
 
165
- #: includes/Admin/Sync_Page.php:109
166
  #. translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s,
167
  #. %4$s - closing </strong> HTML tag
168
  msgid ""
@@ -171,7 +171,7 @@ msgid ""
171
  "price, inventory, category, image%4$s."
172
  msgstr ""
173
 
174
- #: includes/Admin/Sync_Page.php:126
175
  #. translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing
176
  #. </strong> HTML tag
177
  msgid ""
@@ -179,46 +179,46 @@ msgid ""
179
  "Square and WooCommerce."
180
  msgstr ""
181
 
182
- #: includes/Admin/Sync_Page.php:161
183
  msgid "Please connect to Square to enable product sync."
184
  msgstr ""
185
 
186
- #: includes/Admin/Sync_Page.php:163
187
  msgid "Please set the business location to enable product sync."
188
  msgstr ""
189
 
190
- #: includes/Admin/Sync_Page.php:165
191
  msgid "There are currently no products marked to be synced with Square."
192
  msgstr ""
193
 
194
- #: includes/Admin/Sync_Page.php:167
195
  msgid "A sync is currently in progress. Please try again later."
196
  msgstr ""
197
 
198
- #: includes/Admin/Sync_Page.php:172
199
  #. translators: Placeholder: %s - reason text
200
  msgid "Product sync between WooCommerce and Square is currently unavailable. %s"
201
  msgstr ""
202
 
203
- #: includes/Admin/Sync_Page.php:179
204
  msgid "Synced products"
205
  msgstr ""
206
 
207
- #: includes/Admin/Sync_Page.php:180
208
  msgid "Latest sync"
209
  msgstr ""
210
 
211
- #: includes/Admin/Sync_Page.php:181
212
  msgid "Next sync"
213
  msgstr ""
214
 
215
- #: includes/Admin/Sync_Page.php:182 includes/Admin/Sync_Page.php:295
216
- #: includes/Admin/Sync_Page.php:336
217
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:426
218
  msgid "Actions"
219
  msgstr ""
220
 
221
- #: includes/Admin/Sync_Page.php:192 includes/Emails/Sync_Completed.php:207
222
  #. translators: Placeholder: %d number of products synced with Square
223
  #. translators: Placeholder: %d products count
224
  msgid "%d product"
@@ -226,66 +226,67 @@ msgid_plural "%d products"
226
  msgstr[0] ""
227
  msgstr[1] ""
228
 
229
- #: includes/Admin/Sync_Page.php:210
230
  msgid "Importing now&hellip;"
231
  msgstr ""
232
 
233
- #: includes/Admin/Sync_Page.php:212
234
  msgid "Syncing now&hellip;"
235
  msgstr ""
236
 
237
- #: includes/Admin/Sync_Page.php:227
238
  msgid "Not synced yet."
239
  msgstr ""
240
 
241
- #: includes/Admin/Sync_Page.php:259
242
  msgid "Sync now"
243
  msgstr ""
244
 
245
- #: includes/Admin/Sync_Page.php:293 includes/Admin/Sync_Page.php:334
246
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:97
 
247
  msgid "Status"
248
  msgstr ""
249
 
250
- #: includes/Admin/Sync_Page.php:294 includes/Admin/Sync_Page.php:335
251
  msgid "Message"
252
  msgstr ""
253
 
254
- #: includes/Admin/Sync_Page.php:325
255
  msgid "No records found."
256
  msgstr ""
257
 
258
- #: includes/Admin/Sync_Page.php:357
259
  msgid "Sync products with Square"
260
  msgstr ""
261
 
262
- #: includes/Admin/Sync_Page.php:367
263
  msgid ""
264
  "If a match is found in Square, product data in WooCommerce will be "
265
  "overwritten with Square data."
266
  msgstr ""
267
 
268
- #: includes/Admin/Sync_Page.php:369
269
  msgid ""
270
  "If a match is found in WooCommerce, product data in Square will be "
271
  "overwritten with WooCommerce data."
272
  msgstr ""
273
 
274
- #: includes/Admin/Sync_Page.php:373
275
  msgid ""
276
  "If a match is not found in Square, the product will be hidden from the "
277
  "catalog in WooCommerce."
278
  msgstr ""
279
 
280
- #: includes/Admin/Sync_Page.php:375
281
  msgid "If a match is not found in Square, the product will be skipped in the sync."
282
  msgstr ""
283
 
284
- #: includes/Admin/Sync_Page.php:378
285
  msgid "If a match is not found, a new product will be created in Square."
286
  msgstr ""
287
 
288
- #: includes/Admin/Sync_Page.php:385
289
  #. translators: Placeholders: %1$s - the system of record name (e.g. Square or
290
  #. WooCommerce), %3%s - unordered HTML list of additional information item(s)
291
  msgid ""
@@ -293,11 +294,11 @@ msgid ""
293
  "For all products synced with Square: %2$s"
294
  msgstr ""
295
 
296
- #: includes/Admin/Sync_Page.php:394
297
  msgid "Start sync"
298
  msgstr ""
299
 
300
- #: includes/Admin.php:143 includes/Handlers/Products.php:177
301
  msgid "Synced with Square"
302
  msgstr ""
303
 
@@ -309,54 +310,54 @@ msgstr ""
309
  msgid "Fetch stock from Square"
310
  msgstr ""
311
 
312
- #: includes/Admin.php:192 includes/Sync/Records/Record.php:209
313
  msgid "Resolved"
314
  msgstr ""
315
 
316
- #: includes/Admin.php:193
317
  msgid "No records found"
318
  msgstr ""
319
 
320
- #: includes/Admin.php:194
321
  msgid "Skipped"
322
  msgstr ""
323
 
324
- #: includes/Admin.php:195
325
  msgid "Updated"
326
  msgstr ""
327
 
328
- #: includes/Admin.php:196
329
  msgid "Imported"
330
  msgstr ""
331
 
332
- #: includes/Admin.php:198
333
  msgid "Enable to fetch inventory changes from Square"
334
  msgstr ""
335
 
336
- #: includes/Admin.php:199
337
  msgid "Enable to push inventory changes to Square"
338
  msgstr ""
339
 
340
- #: includes/Admin.php:202 includes/Settings.php:233
341
  msgid "Inventory is fetched from Square periodically and updated in WooCommerce"
342
  msgstr ""
343
 
344
- #: includes/Admin.php:205
345
  #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag
346
  msgid ""
347
  "Inventory is %1$salways fetched from Square%2$s periodically to account for "
348
  "sales from other channels."
349
  msgstr ""
350
 
351
- #: includes/Emails/Access_Token_Email.php:45
352
  msgid "Square Access Token problems"
353
  msgstr ""
354
 
355
- #: includes/Emails/Access_Token_Email.php:46
356
  msgid "This email is sent when problems with Access Token are encountered"
357
  msgstr ""
358
 
359
- #: includes/Emails/Access_Token_Email.php:99
360
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
361
  #. </a> HTML link tag
362
  msgid ""
@@ -364,14 +365,14 @@ msgid ""
364
  "re-connect your site%2$s."
365
  msgstr ""
366
 
367
- #: includes/Emails/Access_Token_Email.php:107
368
- #: includes/Emails/Sync_Completed.php:100
369
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
370
  #. </a> HTML link tag
371
  msgid "%1$sInspect status logs%2$s"
372
  msgstr ""
373
 
374
- #: includes/Emails/Access_Token_Email.php:113
375
  msgid ""
376
  "In order to continue accepting payments, please disconnect and re-connect "
377
  "your site at "
@@ -394,1387 +395,1445 @@ msgid ""
394
  "%s"
395
  msgstr ""
396
 
397
- #: includes/Emails/Sync_Completed.php:45
398
  msgid "Square sync completed"
399
  msgstr ""
400
 
401
- #: includes/Emails/Sync_Completed.php:46
402
  msgid ""
403
  "This email is sent once a manual sync has been completed between "
404
  "WooCommerce and Square"
405
  msgstr ""
406
 
407
- #: includes/Emails/Sync_Completed.php:70
408
  msgid "Square sync failed"
409
  msgstr ""
410
 
411
- #: includes/Emails/Sync_Completed.php:107
412
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
413
  #. </a> HTML link tag
414
  msgid "%1$sEnable logging%2$s"
415
  msgstr ""
416
 
417
- #: includes/Emails/Sync_Completed.php:115
418
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
419
  #. </a> HTML link tag, %3$s - additional action
420
  msgid "The sync job has failed. %1$sClick for more details%2$s, or %3$s."
421
  msgstr ""
422
 
423
- #: includes/Emails/Sync_Completed.php:124
424
  msgid "Inspect status logs"
425
  msgstr ""
426
 
427
- #: includes/Emails/Sync_Completed.php:126 includes/Settings.php:269
428
  msgid "Enable Logging"
429
  msgstr ""
430
 
431
- #: includes/Emails/Sync_Completed.php:131
432
  #. translators: Placeholders: %s - additional action
433
  msgid "The sync job has failed. Check sync records, or %s."
434
  msgstr ""
435
 
436
- #: includes/Gateway/API/Requests/Orders.php:84
437
- #: includes/Gateway/Digital_Wallet.php:425
438
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:555
439
- msgid "Discount"
440
  msgstr ""
441
 
442
- #: includes/Gateway/API/Requests/Orders.php:302
443
- #: includes/Gateway/API/Requests/Orders.php:348
444
- msgid "Adjustment"
445
  msgstr ""
446
 
447
- #: includes/Gateway/Blocks_Handler.php:137
448
- #: includes/Gateway/Digital_Wallet.php:209
449
- #: includes/Gateway/Payment_Form.php:240 includes/Gateway.php:245
450
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php:216
451
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2758
452
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:376
453
- msgid "An error occurred, please try again or try an alternate form of payment."
454
  msgstr ""
455
 
456
- #: includes/Gateway/Blocks_Handler.php:152
457
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1102
458
- msgid "Credit Card"
459
  msgstr ""
460
 
461
- #: includes/Gateway/Blocks_Handler.php:298
462
- #. translators: %1$s - opening bold HTML tag, %2$s - closing bold HTML tag,
463
- #. %3$s - version number
464
- msgid ""
465
- "%1$sWarning!%2$s Some Square + Checkout Block features do not work with "
466
- "your version of WooCommerce Blocks (%3$s). Please update to the latest "
467
- "version of WooCommerce Blocks or WooCommerce to fix these issues."
468
  msgstr ""
469
 
470
- #: includes/Gateway/Digital_Wallet.php:114
471
- #. Translators: %1$s: expected location of apple pay verification file, %2$s:
472
- #. opening href tag with link to Square documentation, %3$s: closing href tag
473
  msgid ""
474
- "Apple Pay is not available with Square. We cannot confirm the Apple Pay "
475
- "domain verification file is at the expected location: %1$s. For more "
476
- "information, please read our documentation on %2$sSetting up Apple Pay%3$s."
477
  msgstr ""
478
 
479
- #: includes/Gateway/Digital_Wallet.php:130
480
- #. Translators: %1$s: opening bold tags, %2$s: closing strong/bold tags, %3$s:
481
- #. expected location of apple pay verification file, %4$s: opening href tag
482
- #. with link to Square documentation, %5$s: closing href tag
483
- msgid ""
484
- "Apple Pay is not available with Square - there was a problem with "
485
- "registering your store domain with Square/Apple Pay. %1$sView the Square "
486
- "logs%2$s to find out what caused the registration to fail."
487
  msgstr ""
488
 
489
- #: includes/Gateway/Digital_Wallet.php:178
490
- msgid "OR"
 
 
491
  msgstr ""
492
 
493
- #: includes/Gateway/Digital_Wallet.php:278
494
- #. translators: product ID
495
- msgid "Product with the ID (%d) cannot be found."
496
  msgstr ""
497
 
498
- #: includes/Gateway/Digital_Wallet.php:294
499
- #. translators: 1: product name 2: quantity in stock
500
- msgid ""
501
- "You cannot add that amount of \"%1$s\"; to the cart because there is not "
502
- "enough stock (%2$s remaining)."
503
  msgstr ""
504
 
505
- #: includes/Gateway/Digital_Wallet.php:299
506
- #. translators: 1: product name
507
- msgid "You cannot purchase \"%1$s\" because it is currently not available."
508
  msgstr ""
509
 
510
- #: includes/Gateway/Digital_Wallet.php:321
511
- #: includes/Gateway/Digital_Wallet.php:417
512
- msgid "Tax"
513
  msgstr ""
514
 
515
- #: includes/Gateway/Digital_Wallet.php:356
516
- msgid "This payment method cannot be used for multiple shipments."
517
  msgstr ""
518
 
519
- #: includes/Gateway/Digital_Wallet.php:367
520
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:182
521
- msgid "Pending"
522
  msgstr ""
523
 
524
- #: includes/Gateway/Digital_Wallet.php:409
525
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:565
526
- msgid "Shipping"
527
  msgstr ""
528
 
529
- #: includes/Gateway/Digital_Wallet.php:433
530
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:575
531
- msgid "Fees"
532
  msgstr ""
533
 
534
- #: includes/Gateway/Digital_Wallet.php:468
535
- #. translators: Context (product, cart, checkout or page)
536
- msgid "Empty payment request data for %s."
537
  msgstr ""
538
 
539
- #: includes/Gateway/Digital_Wallet.php:662
540
- msgid "Empty cart"
541
  msgstr ""
542
 
543
- #: includes/Gateway/Digital_Wallet.php:796
544
- msgid "Unable to verify domain with Apple Pay - missing access token."
 
545
  msgstr ""
546
 
547
- #: includes/Gateway/Payment_Form.php:182
548
- msgid "Postal code"
 
 
549
  msgstr ""
550
 
551
- #: includes/Gateway.php:81
552
- msgid "Allow customers to use Square to securely pay with their credit cards"
 
553
  msgstr ""
554
 
555
- #: includes/Gateway.php:443
556
- msgid "Refunds must be made within %s of the original payment date."
557
  msgstr ""
558
 
559
- #: includes/Gateway.php:467
560
- msgid ""
561
- "Could not find original transaction tender. Please refund this transaction "
562
- "from your Square dashboard."
563
  msgstr ""
564
 
565
- #: includes/Gateway.php:580 includes/Gateway.php:750
566
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:107
567
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1143
568
- msgid "Enable / Disable"
569
  msgstr ""
570
 
571
- #: includes/Gateway.php:581
572
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1144
573
- msgid "Enable this gateway"
574
  msgstr ""
575
 
576
- #: includes/Gateway.php:587
577
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1150
578
- msgid "Title"
 
 
579
  msgstr ""
580
 
581
- #: includes/Gateway.php:589
582
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1152
583
- msgid "Payment method title that the customer will see during checkout."
584
  msgstr ""
585
 
586
- #: includes/Gateway.php:594
587
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1157
588
- msgid "Description"
589
  msgstr ""
590
 
591
- #: includes/Gateway.php:596
592
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1159
593
- msgid "Payment method description that the customer will see during checkout."
 
594
  msgstr ""
595
 
596
- #: includes/Gateway.php:623
597
- msgid "Advanced Settings"
598
  msgstr ""
599
 
600
- #: includes/Gateway.php:630
601
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1188
602
- msgid "Detailed Decline Messages"
603
  msgstr ""
604
 
605
- #: includes/Gateway.php:632
606
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1190
607
- msgid ""
608
- "Check to enable detailed decline messages to the customer during checkout "
609
- "when possible, rather than a generic decline message."
610
  msgstr ""
611
 
612
- #: includes/Gateway.php:639
613
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:75
614
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1197
615
  msgid "Debug Mode"
616
  msgstr ""
617
 
618
- #: includes/Gateway.php:642
619
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1200
620
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
621
- msgid ""
622
- "Show Detailed Error Messages and API requests/responses on the checkout "
623
- "page and/or save them to the %1$sdebug log%2$s"
624
  msgstr ""
625
 
626
- #: includes/Gateway.php:645
627
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:85
628
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1203
629
- msgid "Off"
630
  msgstr ""
631
 
632
- #: includes/Gateway.php:646
633
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1204
634
- msgid "Show on Checkout Page"
635
  msgstr ""
636
 
637
- #: includes/Gateway.php:647
638
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:83
639
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1205
640
  msgid "Save to Log"
641
  msgstr ""
642
 
643
- #: includes/Gateway.php:649
644
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1207
645
- #. translators: show debugging information on both checkout page and in the log
646
- msgid "Both"
647
  msgstr ""
648
 
649
- #: includes/Gateway.php:685
650
- msgid "Customer Profiles"
651
  msgstr ""
652
 
653
- #: includes/Gateway.php:686
654
- msgid ""
655
- "Check to enable tokenization and allow customers to securely save their "
656
- "payment details for future checkout."
657
  msgstr ""
658
 
659
- #: includes/Gateway.php:744
660
- msgid "Digital Wallet Settings"
661
  msgstr ""
662
 
663
- #: includes/Gateway.php:745
664
- msgid "Take payments on your store with Apple Pay and Google Pay."
665
  msgstr ""
666
 
667
- #: includes/Gateway.php:752
668
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
669
- msgid ""
670
- "Allow customers to pay with Apple Pay or Google Pay from your Product, Cart "
671
- "and Checkout pages. Read more about the availablity of digital wallets in "
672
- "our %1$sdocumentation%2$s."
673
  msgstr ""
674
 
675
- #: includes/Gateway.php:755
676
- msgid "Enable digital wallets"
677
  msgstr ""
678
 
679
- #: includes/Gateway.php:759
680
- msgid "Button Type"
681
  msgstr ""
682
 
683
- #: includes/Gateway.php:760
684
- msgid ""
685
- "This setting only applies to the Apple Pay button. When Google Pay is "
686
- "available, the Google Pay button will always have the \"Buy with\" button "
687
- "text."
688
  msgstr ""
689
 
690
- #: includes/Gateway.php:761
691
- msgid "Select which text is displayed on the digital wallet buttons."
692
  msgstr ""
693
 
694
- #: includes/Gateway.php:773
695
- msgid "Apple Pay Button Color"
 
696
  msgstr ""
697
 
698
- #: includes/Gateway.php:774
699
- msgid "Select the color of the Apple Pay button."
 
 
 
700
  msgstr ""
701
 
702
- #: includes/Gateway.php:786
703
- msgid "Google Pay Button Color"
 
 
704
  msgstr ""
705
 
706
- #: includes/Gateway.php:787
707
- msgid "Select the color of the Google Pay button."
 
 
708
  msgstr ""
709
 
710
- #: includes/Gateway.php:798
711
- msgid "Hide Digital Wallet Buttons"
712
  msgstr ""
713
 
714
- #: includes/Gateway.php:799
 
 
 
 
715
  msgid ""
716
- "Select any digital wallet buttons you don't want to be displayed on your "
717
- "store."
718
  msgstr ""
719
 
720
- #: includes/Gateway.php:1083
721
- msgid " An error occurred, please try again or try an alternate form of payment."
 
 
 
722
  msgstr ""
723
 
724
- #: includes/Handlers/Background_Job.php:344
725
- msgid "Clear Square Sync"
726
  msgstr ""
727
 
728
- #: includes/Handlers/Background_Job.php:345
729
- msgid "Clear"
730
  msgstr ""
731
 
732
- #: includes/Handlers/Background_Job.php:346
733
- msgid "This tool will clear any ongoing Square product syncs."
734
  msgstr ""
735
 
736
- #: includes/Handlers/Background_Job.php:365
737
- msgid "Success! You can now sync your products."
738
  msgstr ""
739
 
740
- #: includes/Handlers/Connection.php:103 includes/Handlers/Connection.php:171
741
- msgid "Sorry, you do not have permission to manage the Square connection."
742
  msgstr ""
743
 
744
- #: includes/Handlers/Connection.php:115
745
- msgid "Square Error: We could not connect to Square. No access token was given.!"
746
  msgstr ""
747
 
748
- #: includes/Handlers/Connection.php:179
749
- msgid "Disconnected successfully"
750
  msgstr ""
751
 
752
- #: includes/Handlers/Connection.php:386
753
- msgid "Connect with Square"
754
  msgstr ""
755
 
756
- #: includes/Handlers/Connection.php:406
757
- msgid "Disconnect from Square"
758
  msgstr ""
759
 
760
- #: includes/Handlers/Product.php:178
761
- #. translators: Placeholder: %s category ID
762
  msgid ""
763
- "Square category with id (%s) was not imported to your Store. Please run "
764
- "Import Products from Square settings."
765
  msgstr ""
766
 
767
- #: includes/Handlers/Product.php:312
768
- msgid "Product not synced with Square"
 
 
769
  msgstr ""
770
 
771
- #: includes/Handlers/Products.php:68
772
- #. translators: Placeholder: %s - product name
773
  msgid ""
774
- "Please add an SKU to sync %s with Square. The SKU must match the item's SKU "
775
- "in your Square account."
776
  msgstr ""
777
 
778
- #: includes/Handlers/Products.php:70
779
- #. translators: Placeholder: %s - product name
780
  msgid ""
781
- "Please add an SKU to every variation of %s for syncing with Square. Each "
782
- "SKU must be unique and match the corresponding item's SKU in your Square "
783
- "account."
784
  msgstr ""
785
 
786
- #: includes/Handlers/Products.php:72
787
- #. translators: Placeholder: %s - product name
788
- msgid "%s has multiple variation attributes and cannot be synced with Square."
 
789
  msgstr ""
790
 
791
- #: includes/Handlers/Products.php:252
792
- msgid "Update product data with Square data"
793
  msgstr ""
794
 
795
- #: includes/Handlers/Products.php:252
796
- msgid "Send product data to Square"
 
 
797
  msgstr ""
798
 
799
- #: includes/Handlers/Products.php:257
800
- msgid "Sync with Square"
801
  msgstr ""
802
 
803
- #: includes/Handlers/Products.php:293
804
- msgid "Sync with Square?"
 
 
805
  msgstr ""
806
 
807
- #: includes/Handlers/Products.php:297
808
- msgid "No change"
809
  msgstr ""
810
 
811
- #: includes/Handlers/Products.php:299
812
- msgid "No"
813
  msgstr ""
814
 
815
- #: includes/Handlers/Products.php:300
816
- msgid "Yes"
817
  msgstr ""
818
 
819
- #: includes/Handlers/Products.php:306
820
- msgid "This product"
821
  msgstr ""
822
 
823
- #: includes/Handlers/Products.php:677
824
- #. translators: Placeholder: %1$s - date (localized), %2$s - time (localized),
825
- #. %3$s - opening <a> HTML link tag, %4$s closing </a> HTML link tag
826
- msgid ""
827
- "The product catalog visibility has been set to \"hidden\", as a matching "
828
- "product could not be found in Square on %1$s at %2$s. %3$sCheck sync "
829
- "records%4$s."
830
  msgstr ""
831
 
832
- #: includes/Handlers/Sync.php:329
833
- #. translators: Placeholder: %d number of products processed
834
- msgid "Updated data for %d product."
835
- msgid_plural "Updated data for %d products."
836
- msgstr[0] ""
837
- msgstr[1] ""
838
-
839
- #: includes/Lifecycle.php:185
840
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:374
841
- msgid "Awesome"
842
  msgstr ""
843
 
844
- #: includes/Lifecycle.php:186
845
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:377
846
- msgid "Congratulations"
847
  msgstr ""
848
 
849
- #: includes/Lifecycle.php:187
850
- msgid "Great"
851
  msgstr ""
852
 
853
- #: includes/Lifecycle.php:188
854
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:375
855
- msgid "Fantastic"
856
  msgstr ""
857
 
858
- #: includes/Lifecycle.php:195
859
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:385
860
- #. translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a>
861
- #. tag, %4$s - <a> tag, %5$s - </a> tag
862
- msgid ""
863
- "Are you having a great experience with %1$s so far? Please consider "
864
- "%2$sleaving a review%3$s! If things aren't going quite as expected, we're "
865
- "happy to help -- please %4$sreach out to our support team%5$s."
866
  msgstr ""
867
 
868
- #: includes/Plugin.php:290
869
- msgid ""
870
- "Heads up! There may be a problem with your connection to Square. In order "
871
- "to continue accepting payments, please %1$sdisconnect and re-connect your "
872
- "site%2$s."
873
  msgstr ""
874
 
875
- #: includes/Plugin.php:307
876
- msgid "You are connected to Square!"
877
  msgstr ""
878
 
879
- #: includes/Plugin.php:314
880
- msgid "To get started, set your business location."
881
  msgstr ""
882
 
883
- #: includes/Plugin.php:320
884
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
885
- msgid "Visit the %1$splugin settings%2$s to set your business location."
 
886
  msgstr ""
887
 
888
- #: includes/Plugin.php:330
889
- msgid "You are ready to sync products!"
 
890
  msgstr ""
891
 
892
- #: includes/Plugin.php:336
893
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - product count, %3$s -
894
- #. </strong> tag, %4$s - <a> tag, %5$s - </a> tag
895
- msgid ""
896
- "%1$s%2$d products%3$s are marked \"sync with Square\". %4$sStart a new sync "
897
- "now &raquo;%5$s"
898
  msgstr ""
899
 
900
- #: includes/Plugin.php:348
901
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
902
- #. <a> tag, %4$s - </a> tag
903
- msgid ""
904
- "%1$sNo products%2$s are marked \"sync with Square\". %3$sUpdate your "
905
- "products to sync data &raquo;%4$s"
906
  msgstr ""
907
 
908
- #: includes/Plugin.php:363
909
- msgid ""
910
- "Heads up! Square is configured to sync product inventory, but WooCommerce "
911
- "stock management is disabled. Please %1$senable stock management%2$s to "
912
- "ensure product inventory counts are kept in sync."
913
  msgstr ""
914
 
915
- #: includes/Plugin.php:380
916
- msgid "To get started, connect with Square."
 
 
917
  msgstr ""
918
 
919
- #: includes/Plugin.php:386
920
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
921
- msgid "To get started, %1$sconnect with Square &raquo;%2$s"
922
  msgstr ""
923
 
924
- #: includes/Plugin.php:394
925
- #. translators: Placeholders: %1$s - plugin name
926
- msgid "Thanks for installing %1$s!"
927
  msgstr ""
928
 
929
- #: includes/Plugin.php:418
930
- #. translators: Placeholders: %1$s - plugin name, %2$ - plugin version number,
931
- #. %3$s - opening <a> HTML link tag, %4$s - closing </a> HTML link tag, %5$s -
932
- #. opening <a> HTML link tag, %6$s - closing </a> HTML link tag
933
- msgid ""
934
- "%1$s has been updated to version %2$s. In order to continue syncing product "
935
- "inventory, please make sure to disconnect and reconnect with Square from "
936
- "the %3$splugin settings%4$s and re-sync your products. Read more in the "
937
- "%5$supdated documentation%6$s."
938
  msgstr ""
939
 
940
- #: includes/Plugin.php:458
941
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
942
- #. 2-character country code, %4$s - comma separated list of 2-character country
943
- #. codes
944
- msgid ""
945
- "%1$sWooCommerce Square:%2$s Your base country is %3$s, but Square can’t "
946
- "accept transactions from merchants outside of %4$s."
947
  msgstr ""
948
 
949
- #: includes/Plugin.php:485
950
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
951
- #. <a> tag, %4$s - </a> tag
952
- msgid ""
953
- "%1$sWooCommerce Square:%2$s It looks like your site does not support "
954
- "background processing, which means large numbers of products may not sync "
955
- "successfully with Square. %3$sRead more here%4$s on how to resolve this."
956
  msgstr ""
957
 
958
- #: includes/Plugin.php:528
959
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
960
- #. <a> tag, %4$s - </a> tag
961
- msgid ""
962
- "%1$sWooCommerce Square:%2$s Automatic refreshing of the connection to "
963
- "Square is inactive. Please disconnect and reconnect to resolve."
964
  msgstr ""
965
 
966
- #: includes/Plugin.php:560
967
- msgid ""
968
- "%1$sWooCommerce Square:%2$s Product prices are entered inclusive of tax, "
969
- "but Square does not support syncing tax-inclusive prices. Please make sure "
970
- "your Square tax rates match your WooCommerce tax rates."
971
  msgstr ""
972
 
973
- #: includes/Plugin.php:591
974
- msgid ""
975
- "Heads up! Your store currency is %1$s but your configured Square business "
976
- "location currency is %2$s, so payments cannot be processed. Please "
977
- "%3$schoose a different business location%4$s or change your %5$sshop "
978
- "currency%6$s."
979
  msgstr ""
980
 
981
- #. Plugin Name of the plugin/theme
982
- msgid "WooCommerce Square"
983
  msgstr ""
984
 
985
- #: includes/Settings.php:142
986
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
987
- msgid ""
988
- "Sync your products and inventory and also accept credit and debit card "
989
- "payments at checkout. %1$sClick here%2$s to configure payments."
990
  msgstr ""
991
 
992
- #: includes/Settings.php:149
993
  msgid ""
994
- "Connect with Square to start syncing your products and inventory and also "
995
- "accept credit and debit card payments at checkout."
996
  msgstr ""
997
 
998
- #: includes/Settings.php:160
999
- msgid "Enable Sandbox Mode"
 
1000
  msgstr ""
1001
 
1002
- #: includes/Settings.php:161
1003
- msgid "Enable to set the plugin in sandbox mode."
 
1004
  msgstr ""
1005
 
1006
- #: includes/Settings.php:163
1007
- msgid ""
1008
- "After enabling you’ll see a new Sandbox settings section with two fields; "
1009
- "Sandbox Application ID & Sandbox Access Token."
1010
  msgstr ""
1011
 
1012
- #: includes/Settings.php:168
1013
- msgid "Sandbox settings"
 
 
1014
  msgstr ""
1015
 
1016
- #: includes/Settings.php:172
1017
- #. translators: Placeholders: %1$s - URL.
1018
- msgid "Sandbox details can be created at: %s"
1019
  msgstr ""
1020
 
1021
- #: includes/Settings.php:179
1022
- msgid "Sandbox Application ID"
1023
- msgstr ""
 
 
 
 
 
 
 
 
1024
 
1025
- #: includes/Settings.php:181
1026
  msgid ""
1027
- "Application ID for the Sandbox Application, see the details in the My "
1028
- "Applications section."
1029
  msgstr ""
1030
 
1031
- #: includes/Settings.php:186
1032
- msgid "Sandbox Access Token"
1033
  msgstr ""
1034
 
1035
- #: includes/Settings.php:188
1036
- msgid ""
1037
- "Access Token for the Sandbox Test Account, see the details in the Sandbox "
1038
- "Test Account section. Make sure you use the correct Sandbox Access Token "
1039
- "for your application. For a given Sandbox Test Account, each Authorized "
1040
- "Application is assigned a different Access Token."
1041
  msgstr ""
1042
 
1043
- #: includes/Settings.php:195
1044
- msgid "Business location"
1045
  msgstr ""
1046
 
1047
- #: includes/Settings.php:200
1048
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
1049
- #. <a> tag, %4$s - </a> tag
1050
- msgid ""
1051
- "Select a location to link to this site. Only %1$sactive%2$s "
1052
- "%3$slocations%4$s that support credit card processing in Square can be "
1053
- "linked."
1054
  msgstr ""
1055
 
1056
- #: includes/Settings.php:210
1057
- msgid "Product system of record"
1058
  msgstr ""
1059
 
1060
- #: includes/Settings.php:215
1061
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
1062
- #. <a> tag, %4$s - </a> tag
1063
- msgid ""
1064
- "Choose where you will update data for synced products. Inventory in Square "
1065
- "is %1$salways%2$s checked for adjustments when sync is enabled. %3$sClick "
1066
- "here%4$s to read more about choosing a system of record."
1067
  msgstr ""
1068
 
1069
- #: includes/Settings.php:222
1070
- msgid "Do not sync product data"
1071
  msgstr ""
1072
 
1073
- #. Author of the plugin/theme
1074
- msgid "WooCommerce"
1075
  msgstr ""
1076
 
1077
- #: includes/Settings.php:230
1078
- msgid "Sync inventory"
1079
  msgstr ""
1080
 
1081
- #: includes/Settings.php:231
1082
- msgid "Enable to sync product inventory with Square"
 
 
 
 
 
 
 
1083
  msgstr ""
1084
 
1085
- #: includes/Settings.php:237
1086
- msgid "Handle missing products"
1087
  msgstr ""
1088
 
1089
- #: includes/Settings.php:238
1090
- msgid "Hide synced products when not found in Square"
1091
  msgstr ""
1092
 
1093
- #: includes/Settings.php:240
1094
- msgid ""
1095
- "Products not found in Square will be hidden in the WooCommerce product "
1096
- "catalog."
1097
  msgstr ""
1098
 
1099
- #: includes/Settings.php:246
1100
- msgid ""
1101
- "Run an import to create new products in this WooCommerce store for each new "
1102
- "product created in Square that has a unique SKU not existing in here. Needs "
1103
- "to be run each time new items are created in Square."
1104
  msgstr ""
1105
 
1106
- #: includes/Settings.php:256
1107
- msgid "Connection"
 
 
 
1108
  msgstr ""
1109
 
1110
- #: includes/Settings.php:273
1111
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
1112
- msgid "Log debug messages to the %1$sWooCommerce status log%2$s"
 
 
 
 
 
1113
  msgstr ""
1114
 
1115
- #: includes/Settings.php:321
1116
- msgid "Please choose a location"
 
 
 
1117
  msgstr ""
1118
 
1119
- #: includes/Settings.php:355
1120
- msgid "Import all products from Square"
1121
  msgstr ""
1122
 
1123
- #: includes/Sync/Interval_Polling.php:101
1124
- msgid "Updated data for %d category."
1125
- msgid_plural "Updated data for %d categories."
1126
- msgstr[0] ""
1127
- msgstr[1] ""
1128
-
1129
- #: includes/Sync/Interval_Polling.php:111
1130
- msgid ""
1131
- "Product category data could not be updated from Square. Invalid API "
1132
- "response."
1133
  msgstr ""
1134
 
1135
- #: includes/Sync/Manual_Synchronization.php:1141
1136
- #. translators: Placeholder: %s - product ID
1137
- msgid "Product %s could not be updated in Square."
1138
  msgstr ""
1139
 
1140
- #: includes/Sync/Product_Import.php:563
1141
- #. translators: Placeholders: %1$s - Square item name, %2$s - Square item
1142
- #. variation name, %3$s - failure reason
1143
- msgid "Could not import \"%1$s - %2$s\" from Square. %3$s"
1144
  msgstr ""
1145
 
1146
- #: includes/Sync/Product_Import.php:608
1147
- #. translators: Placeholders: %1$s - Square item name, %2$s - failure reason
1148
- msgid "Could not import \"%1$s\" from Square. %2$s"
 
 
 
1149
  msgstr ""
1150
 
1151
- #: includes/Sync/Product_Import.php:637
1152
- msgid "Items with variable pricing cannot be imported."
1153
  msgstr ""
1154
 
1155
- #: includes/Sync/Product_Import.php:641
1156
- msgid "Variations with missing SKUs cannot be imported."
1157
  msgstr ""
1158
 
1159
- #: includes/Sync/Product_Import.php:734 includes/Sync/Product_Import.php:1011
1160
- msgid "The SKU already exists on another product"
1161
  msgstr ""
1162
 
1163
- #: includes/Sync/Product_Import.php:926
1164
- #. translators: Placeholders: %1$s - variation ID, %2$s - product name
1165
- msgid "Variation #%1$s of %2$s"
 
1166
  msgstr ""
1167
 
1168
- #: includes/Sync/Product_Import.php:1305
1169
- #. translators: Placeholders: %s - missing parameter name
1170
- msgid "Missing parameter %s"
 
 
 
1171
  msgstr ""
1172
 
1173
- #: includes/Sync/Product_Import.php:1311
1174
- #. translators: Placeholders: %s - comma separated list of valid product types
1175
- msgid "Invalid product type - the product type must be any of these: %s"
1176
  msgstr ""
1177
 
1178
- #: includes/Sync/Product_Import.php:1362
1179
- #. translators: Placeholders: %1$s - Square item name, %2$s - Failure reason
1180
- msgid "Could not update %1$s from Square. %2$s"
1181
  msgstr ""
1182
 
1183
- #: includes/Sync/Product_Import.php:1365
1184
- #. translators: Placeholders: %1$s - Square item name, %2$s - Failure reason
1185
- msgid "Could not import %1$s from Square. %2$s"
 
1186
  msgstr ""
1187
 
1188
- #: includes/Sync/Records/Record.php:206
1189
- msgid "Info"
1190
  msgstr ""
1191
 
1192
- #: includes/Sync/Records/Record.php:207
1193
- msgid "Notice"
 
1194
  msgstr ""
1195
 
1196
- #: includes/Sync/Records/Record.php:208
1197
- msgid "Alert"
 
 
 
 
1198
  msgstr ""
1199
 
1200
- #: includes/Sync/Records/Record.php:374
1201
- #. translators: Placeholder: %s - product name
1202
- msgid "%s not found in Square."
 
 
 
1203
  msgstr ""
1204
 
1205
- #: includes/Sync/Records/Record.php:545
1206
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:92
1207
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:819
1208
- msgid "Delete"
 
 
1209
  msgstr ""
1210
 
1211
- #: includes/Sync/Records/Record.php:553
1212
- msgid "Ignore"
1213
  msgstr ""
1214
 
1215
- #: includes/Sync/Records/Record.php:562
1216
- msgid "Unlink"
 
1217
  msgstr ""
1218
 
1219
- #: includes/Utilities/Encryption_Utility.php:56
1220
- msgid "Encryption is not supported on this site."
 
 
 
 
1221
  msgstr ""
1222
 
1223
- #: includes/Utilities/Encryption_Utility.php:73
1224
- msgid "%1$s encryption is not available on this site. %2$s will be used instead."
1225
  msgstr ""
1226
 
1227
- #: includes/Utilities/Encryption_Utility.php:98
1228
- msgid "No encryption method available"
1229
  msgstr ""
1230
 
1231
- #: includes/Utilities/Encryption_Utility.php:102
1232
- msgid "Data must be a non-empty string or array"
 
1233
  msgstr ""
1234
 
1235
- #: includes/Utilities/Encryption_Utility.php:106
1236
- #: includes/Utilities/Encryption_Utility.php:149
1237
- msgid "Encryption key must be a string"
1238
  msgstr ""
1239
 
1240
- #: includes/Utilities/Encryption_Utility.php:118
1241
- msgid "Could not generate encryption vector."
 
1242
  msgstr ""
1243
 
1244
- #: includes/Utilities/Encryption_Utility.php:141
1245
- msgid "No decryption method available"
 
1246
  msgstr ""
1247
 
1248
- #: includes/Utilities/Encryption_Utility.php:145
1249
- msgid "Data must be a non-empty string"
 
1250
  msgstr ""
1251
 
1252
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_AdminView.php:48
1253
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_AdminView.php:63
1254
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_AdminView.php:64
1255
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:89
1256
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:19
1257
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:30
1258
- msgid "Scheduled Actions"
1259
  msgstr ""
1260
 
1261
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_InvalidActionException.php:22
1262
- msgid "Action [%s] has invalid arguments. It cannot be JSON decoded to an array."
 
1263
  msgstr ""
1264
 
1265
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:96
1266
- msgid "Hook"
 
1267
  msgstr ""
1268
 
1269
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:98
1270
- msgid "Arguments"
1271
  msgstr ""
1272
 
1273
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:99
1274
- msgid "Group"
1275
  msgstr ""
1276
 
1277
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:100
1278
- msgid "Recurrence"
1279
  msgstr ""
1280
 
1281
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:101
1282
- msgid "Scheduled Date"
1283
  msgstr ""
1284
 
1285
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:102
1286
- msgid "Log"
1287
  msgstr ""
1288
 
1289
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:122
1290
- msgid "Claim ID"
1291
  msgstr ""
1292
 
1293
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:129
1294
- msgid "Run"
1295
  msgstr ""
1296
 
1297
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:130
1298
- msgid "Process the action now as if it were run as part of a queue"
1299
  msgstr ""
1300
 
1301
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:134
1302
- msgid "Cancel the action now to avoid it being run in future"
1303
  msgstr ""
1304
 
1305
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:143
1306
- msgid "%s year"
1307
- msgid_plural "%s years"
1308
- msgstr[0] ""
1309
- msgstr[1] ""
1310
-
1311
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:147
1312
- msgid "%s month"
1313
- msgid_plural "%s months"
1314
- msgstr[0] ""
1315
- msgstr[1] ""
1316
-
1317
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:151
1318
- msgid "%s week"
1319
- msgid_plural "%s weeks"
1320
- msgstr[0] ""
1321
- msgstr[1] ""
1322
-
1323
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:155
1324
- msgid "%s day"
1325
- msgid_plural "%s days"
1326
- msgstr[0] ""
1327
- msgstr[1] ""
1328
-
1329
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:159
1330
- msgid "%s hour"
1331
- msgid_plural "%s hours"
1332
- msgstr[0] ""
1333
- msgstr[1] ""
1334
-
1335
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:163
1336
- msgid "%s minute"
1337
- msgid_plural "%s minutes"
1338
- msgstr[0] ""
1339
- msgstr[1] ""
1340
-
1341
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:167
1342
- msgid "%s second"
1343
- msgid_plural "%s seconds"
1344
- msgstr[0] ""
1345
- msgstr[1] ""
1346
-
1347
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:194
1348
- msgid "Now!"
1349
  msgstr ""
1350
 
1351
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:227
1352
- msgid "Every %s"
1353
  msgstr ""
1354
 
1355
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:231
1356
- msgid "Cron %s"
1357
  msgstr ""
1358
 
1359
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:235
1360
- msgid "Non-repeating"
1361
  msgstr ""
1362
 
1363
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:321
1364
- msgid ""
1365
- "Maximum simultaneous batches already in progress (%s queues). No actions "
1366
- "will be processed until the current batches are complete."
1367
  msgstr ""
1368
 
1369
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:336
1370
- msgid "Successfully executed action: %s"
 
1371
  msgstr ""
1372
 
1373
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:339
1374
- msgid "Successfully canceled action: %s"
1375
  msgstr ""
1376
 
1377
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:342
1378
- msgid "Successfully processed change for action: %s"
 
1379
  msgstr ""
1380
 
1381
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:347
1382
- msgid "Could not process change for action: \"%s\" (ID: %d). Error: %s"
 
1383
  msgstr ""
1384
 
1385
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:392
1386
- msgid " (%s ago)"
 
1387
  msgstr ""
1388
 
1389
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:394
1390
- msgid " (%s)"
 
1391
  msgstr ""
1392
 
1393
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_ListTable.php:531
1394
- msgid "Search hook, args and claim ID"
 
1395
  msgstr ""
1396
 
1397
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:61
1398
- msgid "action created"
 
1399
  msgstr ""
1400
 
1401
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:65
1402
- msgid "action canceled"
 
 
 
1403
  msgstr ""
1404
 
1405
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:69
1406
- msgid "action started"
 
 
 
 
1407
  msgstr ""
1408
 
1409
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:73
1410
- msgid "action complete"
 
1411
  msgstr ""
1412
 
1413
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:77
1414
- msgid "action failed: %s"
 
 
1415
  msgstr ""
1416
 
1417
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:81
1418
- msgid "action timed out after %s seconds"
1419
  msgstr ""
1420
 
1421
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:86
1422
- msgid "unexpected shutdown: PHP Fatal error %s in %s on line %s"
1423
  msgstr ""
1424
 
1425
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:91
1426
- msgid "action reset"
1427
  msgstr ""
1428
 
1429
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Logger.php:95
1430
- msgid "action ignored"
1431
  msgstr ""
1432
 
1433
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_QueueRunner.php:110
1434
- msgid "Every minute"
1435
  msgstr ""
1436
 
1437
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:152
1438
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:169
1439
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:268
1440
- msgid "Invalid schedule. Cannot save action."
1441
  msgstr ""
1442
 
1443
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:181
1444
- msgid "Complete"
1445
  msgstr ""
1446
 
1447
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:183
1448
- msgid "In-progress"
1449
  msgstr ""
1450
 
1451
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:184
1452
- msgid "Failed"
 
1453
  msgstr ""
1454
 
1455
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_Store.php:185
1456
- msgid "Canceled"
 
 
1457
  msgstr ""
1458
 
1459
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:31
1460
- #. translators: %s php class name
1461
- msgid "The %s class can only be run within WP CLI."
1462
  msgstr ""
1463
 
1464
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:59
1465
- msgid "There are too many concurrent batches, but the run is forced to continue."
 
 
1466
  msgstr ""
1467
 
1468
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:61
1469
- msgid "There are too many concurrent batches."
 
 
1470
  msgstr ""
1471
 
1472
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:92
1473
- msgid "Running %d action"
1474
- msgid_plural "Running %d actions"
1475
- msgstr[0] ""
1476
- msgstr[1] ""
1477
-
1478
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:109
1479
- msgid "The claim has been lost. Aborting current batch."
1480
  msgstr ""
1481
 
1482
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:139
1483
- #. translators: %s refers to the action ID
1484
- msgid "Started processing action %s"
 
1485
  msgstr ""
1486
 
1487
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:156
1488
- #. translators: %s refers to the action ID
1489
- msgid "Completed processing action %s with hook: %s"
 
1490
  msgstr ""
1491
 
1492
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:171
1493
- #. translators: %1$s refers to the action ID, %2$s refers to the Exception
1494
- #. message
1495
- msgid "Error processing action %1$s: %2$s"
1496
  msgstr ""
1497
 
1498
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:183
1499
- msgid "second"
1500
- msgid_plural "seconds"
1501
- msgstr[0] ""
1502
- msgstr[1] ""
1503
-
1504
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_QueueRunner.php:187
1505
- msgid "Attempting to reduce used memory..."
1506
  msgstr ""
1507
 
1508
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_Scheduler_command.php:87
1509
- #. translators: %d refers to how many scheduled taks were found to run
1510
- msgid "Found %d scheduled task"
1511
- msgid_plural "Found %d scheduled tasks"
1512
- msgstr[0] ""
1513
- msgstr[1] ""
1514
-
1515
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_Scheduler_command.php:104
1516
- #. translators: %d refers to the total number of batches executed
1517
- msgid "%d batch executed."
1518
- msgid_plural "%d batches executed."
1519
- msgstr[0] ""
1520
- msgstr[1] ""
1521
-
1522
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_Scheduler_command.php:123
1523
- #. translators: %s refers to the exception error message.
1524
- msgid "There was an error running the action scheduler: %s"
1525
  msgstr ""
1526
 
1527
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_WPCLI_Scheduler_command.php:140
1528
- #. translators: %d refers to the total number of taskes completed
1529
- msgid "%d scheduled task completed."
1530
- msgid_plural "%d scheduled tasks completed."
1531
- msgstr[0] ""
1532
- msgstr[1] ""
1533
 
1534
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:27
1535
- msgid "Error saving action: %s"
 
 
1536
  msgstr ""
1537
 
1538
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:51
1539
- msgid "Unable to save action."
 
 
 
1540
  msgstr ""
1541
 
1542
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:441
1543
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:452
1544
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:478
1545
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:755
1546
- msgid "Unidentified action %s"
1547
  msgstr ""
1548
 
1549
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:590
1550
- msgid "Unable to claim actions. Database error."
 
 
1551
  msgstr ""
1552
 
1553
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:610
1554
- msgid "The group \"%s\" does not exist."
 
 
1555
  msgstr ""
1556
 
1557
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:678
1558
- msgid "Unable to unlock claim %s. Database error."
1559
  msgstr ""
1560
 
1561
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:692
1562
- msgid "Unable to unlock claim on action %s. Database error."
 
 
 
1563
  msgstr ""
1564
 
1565
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:703
1566
- msgid "Unable to mark failure on action %s. Database error."
1567
  msgstr ""
1568
 
1569
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore.php:727
1570
- msgid "Invalid action ID. No status found."
 
 
1571
  msgstr ""
1572
 
1573
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php:37
1574
- msgid "Failed <span class=\"count\">(%s)</span>"
1575
- msgid_plural "Failed <span class=\"count\">(%s)</span>"
1576
- msgstr[0] ""
1577
- msgstr[1] ""
1578
 
1579
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php:51
1580
- msgid "In-Progress <span class=\"count\">(%s)</span>"
1581
- msgid_plural "In-Progress <span class=\"count\">(%s)</span>"
1582
- msgstr[0] ""
1583
- msgstr[1] ""
1584
 
1585
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:20
1586
- msgid "Scheduled actions are hooks triggered on a cetain date and time."
1587
  msgstr ""
1588
 
1589
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:31
1590
- msgid "Scheduled Action"
1591
  msgstr ""
1592
 
1593
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:33
1594
- msgid "Add"
1595
  msgstr ""
1596
 
1597
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:34
1598
- msgid "Add New Scheduled Action"
1599
  msgstr ""
1600
 
1601
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:35
1602
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:226
1603
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:758
1604
- msgid "Edit"
1605
  msgstr ""
1606
 
1607
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:36
1608
- msgid "Edit Scheduled Action"
 
 
 
1609
  msgstr ""
1610
 
1611
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:37
1612
- msgid "New Scheduled Action"
 
 
 
1613
  msgstr ""
1614
 
1615
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:38
1616
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:39
1617
- msgid "View Action"
1618
  msgstr ""
1619
 
1620
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:40
1621
- msgid "Search Scheduled Actions"
 
 
1622
  msgstr ""
1623
 
1624
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:41
1625
- msgid "No actions found"
1626
  msgstr ""
1627
 
1628
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:42
1629
- msgid "No actions found in trash"
1630
  msgstr ""
1631
 
1632
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_TaxonomyRegistrar.php:14
1633
- msgid "Action Group"
 
 
 
1634
  msgstr ""
1635
 
1636
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:376
1637
- msgid "Cowabunga"
 
1638
  msgstr ""
1639
 
1640
- #: vendor/skyverge/wc-plugin-framework/woocommerce/Lifecycle.php:378
1641
- msgid "Hot dog"
 
 
1642
  msgstr ""
1643
 
1644
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:183
1645
- msgid ""
1646
- "Thanks for installing %1$s! To get started, take a minute to %2$sread the "
1647
- "documentation%3$s :)"
1648
  msgstr ""
1649
 
1650
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:211
1651
- msgid ""
1652
- "Thanks for installing %1$s! To get started, take a minute to complete these "
1653
- "%2$squick and easy setup steps%3$s :)"
 
 
 
 
 
 
 
1654
  msgstr ""
1655
 
1656
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:236
1657
- msgid "Setup"
1658
  msgstr ""
1659
 
1660
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:304
1661
- #. translators: Placeholders: %s - plugin name
1662
- msgid "%s &rsaquo; Setup"
 
1663
  msgstr ""
1664
 
1665
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:352
1666
- msgid "Oops! An error occurred, please try again."
1667
  msgstr ""
1668
 
1669
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:490
1670
- msgid "Ready!"
1671
  msgstr ""
1672
 
1673
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:583
1674
- #. translators: Placeholder: %s - plugin name
1675
- msgid "Welcome to %s!"
1676
  msgstr ""
1677
 
1678
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:596
1679
- msgid ""
1680
- "This quick setup wizard will help you configure the basic settings and get "
1681
- "you started."
 
 
 
 
 
 
 
 
1682
  msgstr ""
1683
 
1684
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:610
1685
- msgid "%s is ready!"
1686
  msgstr ""
1687
 
1688
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:662
1689
- msgid "Next step"
1690
  msgstr ""
1691
 
1692
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:688
1693
- msgid "You can also:"
1694
  msgstr ""
1695
 
1696
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:732
1697
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:762
1698
- msgid "View the Docs"
1699
  msgstr ""
1700
 
1701
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:733
1702
- msgid "See more setup options"
1703
  msgstr ""
1704
 
1705
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:734
1706
- msgid "Learn more about customizing the plugin"
1707
  msgstr ""
1708
 
1709
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:758
1710
- msgid "Review Your Settings"
1711
  msgstr ""
1712
 
1713
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:766
1714
- msgid "Leave a Review"
1715
  msgstr ""
1716
 
1717
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:790
1718
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:660
1719
- msgid "Continue"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1720
  msgstr ""
1721
 
1722
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:950
1723
- msgid "Return to the WordPress Dashboard"
1724
  msgstr ""
1725
 
1726
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:952
1727
- msgid "Not right now"
 
1728
  msgstr ""
1729
 
1730
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:954
1731
- msgid "Skip this step"
 
 
 
 
1732
  msgstr ""
1733
 
1734
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:268
 
1735
  msgid ""
1736
- "The following plugin is disabled because it is out of date and incompatible "
1737
- "with newer plugins on your site:"
1738
- msgid_plural ""
1739
- "The following plugins are disabled because they are out of date and "
1740
- "incompatible with newer plugins on your site:"
1741
- msgstr[0] ""
1742
- msgstr[1] ""
1743
 
1744
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:282
 
 
1745
  msgid ""
1746
- "To resolve this, please %1$supdate%2$s (recommended) %3$sor%4$s "
1747
- "%5$sdeactivate%6$s the above plugin, or %7$sdeactivate the following%8$s:"
1748
  msgid_plural ""
1749
- "To resolve this, please %1$supdate%2$s (recommended) %3$sor%4$s "
1750
- "%5$sdeactivate%6$s the above plugins, or %7$sdeactivate the following%8$s:"
1751
  msgstr[0] ""
1752
  msgstr[1] ""
1753
 
1754
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1755
  msgid ""
1756
- "The following plugins are inactive because they require a newer version of "
1757
- "WooCommerce:"
1758
  msgstr ""
1759
 
1760
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:303
1761
  msgid ""
1762
- "The following plugin is inactive because it requires a newer version of "
1763
- "WooCommerce:"
1764
  msgstr ""
1765
 
1766
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:308
1767
- #. translators: Placeholders: %1$s - plugin name, %2$s - WooCommerce version
1768
- #. number
1769
- msgid "%1$s requires WooCommerce %2$s or newer"
1770
  msgstr ""
1771
 
1772
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-framework-bootstrap.php:312
1773
- #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
1774
- msgid "Please %1$supdate WooCommerce%2$s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1775
  msgstr ""
1776
 
1777
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:148
1778
  #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP
1779
  #. extension/comma-separated list of PHP extensions
1780
  msgid ""
@@ -1787,7 +1846,7 @@ msgid_plural ""
1787
  msgstr[0] ""
1788
  msgstr[1] ""
1789
 
1790
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:176
1791
  #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP
1792
  #. function/comma-separated list of PHP functions
1793
  msgid ""
@@ -1799,24 +1858,25 @@ msgid_plural ""
1799
  msgstr[0] ""
1800
  msgstr[1] ""
1801
 
1802
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:206
1803
  #. translators: Placeholders: %s - plugin name
1804
  msgid ""
1805
  "%s may behave unexpectedly because the following PHP configuration settings "
1806
  "are required:"
1807
  msgstr ""
1808
 
1809
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:220
 
1810
  msgid "%s or higher"
1811
  msgstr ""
1812
 
1813
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:230
1814
  msgid ""
1815
  "Please contact your hosting provider or server administrator to configure "
1816
  "these settings."
1817
  msgstr ""
1818
 
1819
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:252
1820
  #. translators: Placeholders: %1$s - <strong>, %2$s - </strong>
1821
  msgid ""
1822
  "Hey there! We've noticed that your server is running %1$san outdated "
@@ -1831,7 +1891,7 @@ msgid ""
1831
  "resources to help you upgrade%5$s and to explain PHP versions further."
1832
  msgstr ""
1833
 
1834
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin-dependencies.php:271
1835
  #. translators: Placeholders: %1$s - WooCommerce version number, %2$s -
1836
  #. <strong>, %3$s - </strong>, %4$s - Plugin name, %5$s - <a> tag, %6$s - </a>
1837
  #. tag
@@ -1842,1400 +1902,1338 @@ msgid ""
1842
  "soon as possible."
1843
  msgstr ""
1844
 
1845
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:297
1846
- #. translators: Placeholders: %s - plugin name
1847
- msgid "You cannot clone instances of %s."
1848
- msgstr ""
1849
-
1850
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:308
1851
- #. translators: Placeholders: %s - plugin name
1852
- msgid "You cannot unserialize instances of %s."
1853
- msgstr ""
1854
-
1855
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:529
1856
- #. translators: Docs as in Documentation
1857
- msgid "Docs"
1858
- msgstr ""
1859
-
1860
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:622
1861
- msgid "%1$s - A minimum of %2$s is required."
1862
  msgstr ""
1863
 
1864
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:631
1865
- msgid "Set as %1$s - %2$s is required."
 
1866
  msgstr ""
1867
 
1868
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:854
1869
- msgid "Configure"
 
 
 
 
 
1870
  msgstr ""
1871
 
1872
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php:178
 
 
1873
  msgid ""
1874
- "There was a problem processing your order and it is being placed on hold "
1875
- "for review. Please contact us to complete the transaction."
 
1876
  msgstr ""
1877
 
1878
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php:319
1879
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:444
1880
- #. translators: Placeholders: %s - a WooCommerce order ID
1881
- msgid "Could not find order %s"
1882
- msgstr ""
1883
-
1884
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:151
1885
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2351
1886
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:163
1887
- #. translators: Placeholders: %1$s - status code, %2$s - status message
1888
- #. translators: Placeholders: %1$s - payment request response status code, %2$s
1889
- #. - payment request response status message
1890
- msgid "Status code %1$s: %2$s"
1891
- msgstr ""
1892
-
1893
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:154
1894
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2354
1895
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:166
1896
- #. translators: Placeholders: %s - status code
1897
- #. translators: Placeholders: %s - payment request response status code
1898
- msgid "Status code: %s"
1899
- msgstr ""
1900
-
1901
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:157
1902
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2357
1903
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:169
1904
- #. translators: Placeholders; %s - status message
1905
- #. translators: Placeholders: %s - payment request response status message
1906
- msgid "Status message: %s"
1907
- msgstr ""
1908
-
1909
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:162
1910
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2362
1911
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:176
1912
- msgid "Transaction ID %s"
1913
  msgstr ""
1914
 
1915
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:203
1916
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:508
1917
- #. translators: Placeholders: %s - payment gateway title (such as
1918
- #. Authorize.net, Braintree, etc)
1919
- msgid "%s duplicate transaction received"
1920
  msgstr ""
1921
 
1922
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:206
1923
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:511
1924
- msgid "Order %s is already paid for."
1925
  msgstr ""
1926
 
1927
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:266
1928
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2694
1929
  msgid ""
1930
- "Your order has been received and is being reviewed. Thank you for your "
1931
- "business."
1932
- msgstr ""
1933
-
1934
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:273
1935
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:851
1936
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1732
1937
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:363
1938
- #. translators: This is a message describing that the transaction in question
1939
- #. only performed a credit card authorization and did not capture any funds.
1940
- msgid "Authorization only transaction"
1941
- msgstr ""
1942
-
1943
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:361
1944
- #. translators: Placeholders: %s - payment gateway title
1945
- msgid "%s Transaction Held for Review"
1946
  msgstr ""
1947
 
1948
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:432
1949
- #. translators: Placeholders: %s - payment gateway title
1950
- msgid "%s Payment Failed"
1951
  msgstr ""
1952
 
1953
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Abstract_Payment_Handler.php:459
1954
- #. translators: Placeholders: %s - payment gateway title
1955
- msgid "%s Transaction Cancelled"
1956
  msgstr ""
1957
 
1958
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:157
1959
- msgid "Order cannot be captured"
1960
  msgstr ""
1961
 
1962
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:162
1963
- msgid "Transaction authorization has expired"
 
1964
  msgstr ""
1965
 
1966
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:167
1967
- msgid "Transaction has already been fully captured"
 
1968
  msgstr ""
1969
 
1970
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:172
1971
- msgid "Transaction cannot be captured"
1972
  msgstr ""
1973
 
1974
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:188
1975
- #. translators: Placeholders: %1$s - payment gateway title (such as
1976
- #. Authorize.net, Braintree, etc), %2$s - transaction amount. Definitions:
1977
- #. Capture, as in capture funds from a credit card.
1978
- msgid "%1$s Capture of %2$s Approved"
1979
  msgstr ""
1980
 
1981
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:195
1982
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:670
1983
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:755
1984
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2030
1985
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2261
1986
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2575
1987
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2620
1988
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:346
1989
- #. translators: Placeholders: %s - transaction ID
1990
- msgid "(Transaction ID %s)"
1991
  msgstr ""
1992
 
1993
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/Handlers/Capture.php:226
1994
- #. translators: Placeholders: %1$s - payment gateway title (such as
1995
- #. Authorize.net, Braintree, etc), %2$s - failure message. Definitions:
1996
- #. "capture" as in capturing funds from a credit card.
1997
- msgid "%1$s Capture Failed: %2$s"
1998
  msgstr ""
1999
 
2000
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:119
2001
- msgid "Are you sure you wish to process this capture? The action cannot be undone."
2002
  msgstr ""
2003
 
2004
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:122
2005
  msgid ""
2006
- "Something went wrong, and the capture could no be completed. Please try "
2007
- "again."
2008
- msgstr ""
2009
-
2010
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:166
2011
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:241
2012
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:304
2013
- #. translators: verb, as in "Capture credit card charge". Used when an
2014
- #. amount has been pre-authorized before, but funds have not yet been captured
2015
- #. (taken) from the card. Capturing the charge will take the money from the
2016
- #. credit card and put it in the merchant's pockets.
2017
- msgid "Capture Charge"
2018
- msgstr ""
2019
-
2020
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:294
2021
- msgid "This charge has been fully captured."
2022
- msgstr ""
2023
-
2024
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:296
2025
- msgid "This charge can no longer be captured."
2026
  msgstr ""
2027
 
2028
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-order.php:298
2029
- msgid "This charge cannot be captured."
2030
  msgstr ""
2031
 
2032
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:90
2033
- msgid "Are you sure you want to remove this token?"
2034
  msgstr ""
2035
 
2036
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:100
2037
- msgid "Invalid token data"
 
 
2038
  msgstr ""
2039
 
2040
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:104
2041
- msgid "An error occurred. Please try again."
2042
  msgstr ""
2043
 
2044
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:453
2045
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-user-handler.php:302
2046
- msgid "(%s)"
2047
  msgstr ""
2048
 
2049
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:483
2050
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:664
2051
- msgid "Default"
 
 
 
2052
  msgstr ""
2053
 
2054
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:519
2055
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:552
2056
- msgid "Token ID"
2057
  msgstr ""
2058
 
2059
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:524
2060
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:299
2061
- msgid "Card Type"
2062
  msgstr ""
2063
 
2064
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:529
2065
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:565
2066
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:191
2067
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:297
2068
- msgid "Last Four"
2069
  msgstr ""
2070
 
2071
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:536
2072
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:320
2073
- msgid "Expiration (MM/YY)"
2074
  msgstr ""
2075
 
2076
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:557
2077
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:427
2078
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:298
2079
- #. translators: e-check account type, HTML form field label
2080
- msgid "Account Type"
2081
  msgstr ""
2082
 
2083
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:560
2084
- msgid "Checking"
2085
  msgstr ""
2086
 
2087
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:561
2088
- msgid "Savings"
2089
  msgstr ""
2090
 
2091
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:662
2092
- msgid "Refresh"
2093
  msgstr ""
2094
 
2095
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:664
2096
- msgid "Add New"
2097
  msgstr ""
2098
 
2099
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:667
2100
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:759
2101
- msgid "Save"
 
2102
  msgstr ""
2103
 
2104
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-payment-token-editor.php:690
2105
- msgid "Remove"
2106
  msgstr ""
2107
 
2108
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-user-handler.php:221
2109
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:208
2110
- msgid "%s Payment Tokens"
2111
  msgstr ""
2112
 
2113
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/class-sv-wc-payment-gateway-admin-user-handler.php:299
2114
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:663
2115
- msgid "Customer ID"
2116
  msgstr ""
2117
 
2118
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:32
2119
- msgid "This section contains configuration settings for this gateway."
2120
  msgstr ""
2121
 
2122
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:53
2123
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1267
2124
- #. translators: environment as in a software environment (test/production)
2125
- msgid "Environment"
2126
  msgstr ""
2127
 
2128
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:54
2129
- msgid "The transaction environment for this gateway."
2130
  msgstr ""
2131
 
2132
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:61
2133
- msgid "Tokenization Enabled"
2134
  msgstr ""
2135
 
2136
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:62
2137
- msgid "Displays whether or not tokenization is enabled for this gateway."
2138
  msgstr ""
2139
 
2140
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:76
2141
- msgid "Displays whether or not debug logging is enabled for this gateway."
2142
  msgstr ""
2143
 
2144
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:79
2145
- msgid "Display at Checkout & Log"
2146
  msgstr ""
2147
 
2148
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-admin-gateway-status.php:81
2149
- msgid "Display at Checkout"
 
 
 
2150
  msgstr ""
2151
 
2152
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:30
2153
- msgid "Authorization total"
2154
  msgstr ""
2155
 
2156
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:34
2157
- msgid "Amount already captured"
 
 
 
2158
  msgstr ""
2159
 
2160
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:40
2161
- msgid "Remaining order total"
 
 
 
 
2162
  msgstr ""
2163
 
2164
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:46
2165
- msgid "Capture amount"
 
2166
  msgstr ""
2167
 
2168
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:53
2169
- msgid "Comment (optional):"
2170
  msgstr ""
2171
 
2172
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-order-partial-capture.php:65
2173
- msgid "Capture %s"
2174
  msgstr ""
2175
 
2176
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-user-payment-token-editor-token.php:48
2177
- msgid "-- Select an option --"
2178
  msgstr ""
2179
 
2180
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-user-payment-token-editor.php:59
2181
- msgid "No saved payment tokens"
2182
  msgstr ""
2183
 
2184
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/admin/views/html-user-profile-field-customer-id.php:30
2185
- msgid "The gateway customer ID for the user. Only edit this if necessary."
2186
  msgstr ""
2187
 
2188
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:98
2189
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:131
2190
- msgid "An error occurred, please try again or try an alternate form of payment"
2191
  msgstr ""
2192
 
2193
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:99
2194
- msgid ""
2195
- "We cannot process your order with the payment information that you "
2196
- "provided. Please use a different payment account or an alternate payment "
2197
- "method."
2198
  msgstr ""
2199
 
2200
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:100
2201
- msgid ""
2202
- "This order is being placed on hold for review. Please contact us to "
2203
- "complete the transaction."
2204
  msgstr ""
2205
 
2206
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:105
 
 
2207
  msgid ""
2208
- "This order is being placed on hold for review due to an incorrect card "
2209
- "verification number. You may contact the store to complete the transaction."
 
2210
  msgstr ""
2211
 
2212
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:106
2213
- msgid "The card verification number is invalid, please try again."
2214
- msgstr ""
 
 
 
2215
 
2216
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:107
2217
- msgid "Please enter your card verification number and try again."
2218
  msgstr ""
2219
 
2220
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:110
2221
  msgid ""
2222
- "That card type is not accepted, please use an alternate card or other form "
2223
- "of payment."
 
2224
  msgstr ""
2225
 
2226
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:111
2227
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:115
2228
- msgid ""
2229
- "The card type is invalid or does not correlate with the credit card number. "
2230
- " Please try again or use an alternate card or other form of payment."
2231
  msgstr ""
2232
 
2233
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:112
2234
- msgid "Please select the card type and try again."
2235
  msgstr ""
2236
 
2237
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:116
2238
- msgid "The card number is invalid, please re-enter and try again."
 
2239
  msgstr ""
2240
 
2241
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:117
2242
- msgid "Please enter your card number and try again."
2243
  msgstr ""
2244
 
2245
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:120
2246
- msgid "The card expiration date is invalid, please re-enter and try again."
 
 
 
 
2247
  msgstr ""
2248
 
2249
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:121
2250
- msgid "The card expiration month is invalid, please re-enter and try again."
 
 
 
 
2251
  msgstr ""
2252
 
2253
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:122
2254
- msgid "The card expiration year is invalid, please re-enter and try again."
 
 
 
2255
  msgstr ""
2256
 
2257
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:123
2258
- msgid "Please enter your card expiration date and try again."
2259
  msgstr ""
2260
 
2261
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:126
2262
- msgid "The bank routing number is invalid, please re-enter and try again."
 
2263
  msgstr ""
2264
 
2265
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:127
2266
- msgid "The bank account number is invalid, please re-enter and try again."
 
2267
  msgstr ""
2268
 
2269
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:130
 
 
 
2270
  msgid ""
2271
- "The provided card is expired, please use an alternate card or other form of "
2272
- "payment."
 
 
2273
  msgstr ""
2274
 
2275
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:131
 
 
 
2276
  msgid ""
2277
- "The provided card was declined, please use an alternate card or other form "
2278
- "of payment."
2279
  msgstr ""
2280
 
2281
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:132
 
 
2282
  msgid ""
2283
- "Insufficient funds in account, please use an alternate card or other form "
2284
- "of payment."
2285
  msgstr ""
2286
 
2287
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:133
2288
  msgid ""
2289
- "The card is inactivate or not authorized for card-not-present transactions, "
2290
- "please use an alternate card or other form of payment."
 
2291
  msgstr ""
2292
 
2293
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:134
2294
  msgid ""
2295
- "The credit limit for the card has been reached, please use an alternate "
2296
- "card or other form of payment."
 
 
2297
  msgstr ""
2298
 
2299
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:135
2300
- msgid "The card verification number does not match. Please re-enter and try again."
2301
  msgstr ""
2302
 
2303
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/api/class-sv-wc-payment-gateway-api-response-message-helper.php:136
 
2304
  msgid ""
2305
- "The provided address does not match the billing address for cardholder. "
2306
- "Please verify the address and try again."
2307
- msgstr ""
2308
-
2309
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:83
2310
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:101
2311
- msgid "Apple Pay"
2312
- msgstr ""
2313
-
2314
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:108
2315
- msgid "Accept Apple Pay"
2316
- msgstr ""
2317
-
2318
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:115
2319
- msgid "Allow Apple Pay on"
2320
- msgstr ""
2321
-
2322
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:125
2323
- msgid "Button Style"
2324
- msgstr ""
2325
-
2326
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:128
2327
- msgid "Black"
2328
- msgstr ""
2329
-
2330
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:129
2331
- msgid "White"
2332
- msgstr ""
2333
-
2334
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:130
2335
- msgid "White with outline"
2336
  msgstr ""
2337
 
2338
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:142
2339
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1318
2340
- msgid "Connection Settings"
 
2341
  msgstr ""
2342
 
2343
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:148
2344
- msgid "Apple Merchant ID"
2345
  msgstr ""
2346
 
2347
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:152
2348
- msgid "This is found in your %1$sApple developer account%2$s"
2349
  msgstr ""
2350
 
2351
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:159
2352
- msgid "Certificate Path"
 
 
2353
  msgstr ""
2354
 
2355
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:164
2356
- #. translators: Placeholders: %s - the server's web root path
2357
- msgid "For reference, your current web root path is: %s"
2358
  msgstr ""
2359
 
2360
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:177
2361
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:187
2362
- msgid "Processing Gateway"
2363
  msgstr ""
2364
 
2365
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:195
2366
- msgid "Test Mode"
2367
  msgstr ""
2368
 
2369
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:196
2370
  msgid ""
2371
- "Enable to test Apple Pay functionality throughout your sites without "
2372
- "processing real payments."
2373
  msgstr ""
2374
 
2375
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:305
2376
- msgid "Your site must be served over HTTPS with a valid SSL certificate."
2377
  msgstr ""
2378
 
2379
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:315
2380
- #. translators: Placeholders: %1$s - plugin name, %2$s - a
2381
- #. currency/comma-separated list of currencies, %3$s - <a> tag, %4$s - </a> tag
2382
- msgid ""
2383
- "Accepts payment in %1$s only. %2$sConfigure%3$s WooCommerce to accept %1$s "
2384
- "to enable Apple Pay."
2385
- msgid_plural ""
2386
- "Accepts payment in one of %1$s only. %2$sConfigure%3$s WooCommerce to "
2387
- "accept one of %1$s to enable Apple Pay."
2388
- msgstr[0] ""
2389
- msgstr[1] ""
2390
-
2391
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:334
2392
  msgid ""
2393
- "Your %1$sMerchant Identity Certificate%2$s cannot be found. Please check "
2394
- "your path configuration."
2395
- msgstr ""
2396
-
2397
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:341
2398
- msgid "Apple Pay is disabled."
2399
- msgstr ""
2400
-
2401
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:380
2402
- msgid "Single products"
2403
- msgstr ""
2404
-
2405
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:381
2406
- msgid "Cart"
2407
  msgstr ""
2408
 
2409
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-admin.php:382
2410
- msgid "Checkout"
2411
  msgstr ""
2412
 
2413
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:168
2414
- msgid "Buy with"
 
 
 
 
 
2415
  msgstr ""
2416
 
2417
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:302
2418
- msgid "Pay with"
2419
  msgstr ""
2420
 
2421
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-frontend.php:308
2422
- msgid "or"
 
 
 
 
 
2423
  msgstr ""
2424
 
2425
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:86
2426
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:93
2427
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:106
2428
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:115
2429
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:127
2430
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:171
2431
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:181
2432
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay-orders.php:183
2433
- msgid "Error %d: Unable to create order. Please try again."
2434
  msgstr ""
2435
 
2436
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:120
2437
- msgid "Apple Pay payment authorized."
2438
  msgstr ""
2439
 
2440
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:156
2441
- msgid "Apple Pay payment failed. %s"
2442
  msgstr ""
2443
 
2444
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:545
2445
- msgid "Subtotal"
2446
  msgstr ""
2447
 
2448
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/apple-pay/class-sv-wc-payment-gateway-apple-pay.php:585
2449
- msgid "Taxes"
2450
  msgstr ""
2451
 
2452
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:60
2453
  msgid ""
2454
- "Payment error, please try another payment method or contact us to complete "
2455
- "your transaction."
2456
- msgstr ""
2457
-
2458
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:160
2459
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:479
2460
- msgid "Card expiration date is invalid"
2461
  msgstr ""
2462
 
2463
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:184
2464
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:472
2465
- msgid "Card number is missing"
 
 
2466
  msgstr ""
2467
 
2468
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:190
2469
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:475
2470
- msgid "Card number is invalid (wrong length)"
2471
  msgstr ""
2472
 
2473
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:195
2474
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:474
2475
- msgid "Card number is invalid (only digits allowed)"
2476
  msgstr ""
2477
 
2478
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:200
2479
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:473
2480
- msgid "Card number is invalid"
2481
  msgstr ""
2482
 
2483
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:227
2484
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:477
2485
- msgid "Card security code is invalid (only digits are allowed)"
2486
  msgstr ""
2487
 
2488
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:233
2489
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:478
2490
- msgid "Card security code is invalid (must be 3 or 4 digits)"
2491
- msgstr ""
 
2492
 
2493
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:239
2494
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:476
2495
- msgid "Card security code is missing"
 
2496
  msgstr ""
2497
 
2498
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:266
2499
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:488
2500
- msgid "Routing Number is missing"
2501
  msgstr ""
2502
 
2503
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:273
2504
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:489
2505
- msgid "Routing Number is invalid (only digits are allowed)"
 
2506
  msgstr ""
2507
 
2508
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:279
2509
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:490
2510
- msgid "Routing number is invalid (must be 9 digits)"
2511
  msgstr ""
2512
 
2513
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:288
2514
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:485
2515
- msgid "Account Number is missing"
2516
  msgstr ""
2517
 
2518
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:295
2519
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:486
2520
- msgid "Account Number is invalid (only digits are allowed)"
2521
  msgstr ""
2522
 
2523
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:301
2524
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:487
2525
- msgid "Account number is invalid (must be between 5 and 17 digits)"
2526
  msgstr ""
2527
 
2528
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:308
2529
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:484
2530
- msgid "Drivers license number is invalid"
2531
  msgstr ""
2532
 
2533
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:314
2534
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:480
2535
- msgid "Check Number is invalid (only digits are allowed)"
2536
  msgstr ""
2537
 
2538
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:484
2539
- msgid "Unknown error"
 
2540
  msgstr ""
2541
 
2542
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:493
2543
- msgid "Payment method address could not be updated. %s"
 
2544
  msgstr ""
2545
 
2546
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:660
2547
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2610
2548
- #. translators: Placeholders: %1$s - payment method title, %2$s - payment
2549
- #. account type (savings/checking) (may or may not be available), %3$s - last
2550
- #. four digits of the account
2551
- msgid "%1$s Check Transaction Approved: %2$s account ending in %3$s"
2552
  msgstr ""
2553
 
2554
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:665
2555
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2615
2556
- #. translators: Placeholders: %s - check number
2557
- msgid "Check number %s"
2558
  msgstr ""
2559
 
2560
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:734
2561
- #. translators: Placeholders: %1$s - payment method title, %2$s - environment
2562
- #. ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type
2563
- #. (mastercard, visa, ...), %5$s - last four digits of the card
2564
- msgid "%1$s %2$s %3$s Approved: %4$s ending in %5$s"
2565
  msgstr ""
2566
 
2567
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:747
2568
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:675
2569
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2567
2570
- #. translators: Placeholders: %s - expiry date
2571
- msgid "(expires %s)"
2572
  msgstr ""
2573
 
2574
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:819
2575
- #. translators: Placeholders: %s - failure message
2576
- msgid "Tokenization Request Failed: %s"
2577
  msgstr ""
2578
 
2579
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:830
2580
- #. translators: Placeholders: %1$s - payment method title, %2$s - failure
2581
- #. message
2582
- msgid "%1$s Tokenization Request Failed: %2$s"
2583
  msgstr ""
2584
 
2585
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:888
2586
- #. translators: Placeholders: %s - failure message. Payment method as in a
2587
- #. specific credit card, e-check or bank account
2588
- msgid "Oops, adding your new payment method failed: %s"
2589
  msgstr ""
2590
 
2591
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:929
2592
- #. translators: Payment method as in a specific credit card. Placeholders: %1$s
2593
- #. - card type (visa, mastercard, ...), %2$s - last four digits of the card,
2594
- #. %3$s - card expiry date
2595
- msgid "Nice! New payment method added: %1$s ending in %2$s (expires %3$s)"
2596
  msgstr ""
2597
 
2598
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:939
2599
- #. translators: Payment method as in a specific e-check account. Placeholders:
2600
- #. %1$s - account type (checking/savings), %2$s - last four digits of the
2601
- #. account
2602
- msgid "Nice! New payment method added: %1$s account ending in %2$s"
2603
  msgstr ""
2604
 
2605
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:946
2606
- #. translators: Payment method as in a specific credit card, e-check or bank
2607
- #. account
2608
- msgid "Nice! New payment method added."
2609
  msgstr ""
2610
 
2611
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:1066
2612
- #. translators: Placeholders: %1$s - site title, %2$s - customer email. Payment
2613
- #. method as in a specific credit card, e-check or bank account
2614
- msgid "%1$s - Add Payment Method for %2$s"
2615
  msgstr ""
2616
 
2617
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:179
2618
- msgid "PayPal"
 
2619
  msgstr ""
2620
 
2621
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:180
2622
- msgid "Checking Account"
2623
  msgstr ""
2624
 
2625
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:181
2626
- msgid "Savings Account"
2627
  msgstr ""
2628
 
2629
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:182
2630
- msgid "Credit / Debit Card"
2631
  msgstr ""
2632
 
2633
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:183
2634
- msgid "Bank Account"
2635
  msgstr ""
2636
 
2637
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:296
2638
- msgid "Thank you for your order, please click the button below to pay."
 
 
 
 
 
2639
  msgstr ""
2640
 
2641
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:297
2642
- msgid "Thank you for your order. We are now redirecting you to complete payment."
2643
  msgstr ""
2644
 
2645
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:298
2646
- msgid "Pay Now"
2647
  msgstr ""
2648
 
2649
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:299
2650
- msgid "Cancel Order"
 
 
 
 
2651
  msgstr ""
2652
 
2653
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:596
2654
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:832
2655
- #. translators: Placeholders: %1$s - payment gateway title (such as
2656
- #. Authorize.net, Braintree, etc), %2$s - payment method name (mastercard, bank
2657
- #. account, etc), %3$s - last four digits of the card/account, %4$s -
2658
- #. card/account expiry date
2659
- msgid "%1$s Payment Method Saved: %2$s ending in %3$s (expires %4$s)"
2660
  msgstr ""
2661
 
2662
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:607
2663
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:843
2664
- #. translators: Placeholders: %1$s - payment gateway title (such as CyberSouce,
2665
- #. NETbilling, etc), %2$s - account type (checking/savings - may or may not be
2666
- #. available), %3$s - last four digits of the account
2667
- msgid "%1$s eCheck Payment Method Saved: %2$s account ending in %3$s"
2668
  msgstr ""
2669
 
2670
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:616
2671
- #. translators: Placeholders: %s - payment gateway title (such as CyberSouce,
2672
- #. NETbilling, etc)
2673
- msgid "%s Payment Method Saved"
2674
  msgstr ""
2675
 
2676
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php:625
2677
- #. translators: Placeholders: %s - a failed tokenization API error
2678
- msgid "Tokenization failed. %s"
2679
  msgstr ""
2680
 
2681
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:228
2682
- msgid "Oops, there was an error updating your payment method. Please try again."
2683
  msgstr ""
2684
 
2685
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:229
2686
- msgid "Are you sure you want to delete this payment method?"
 
2687
  msgstr ""
2688
 
2689
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:287
2690
- #. translators: Payment method as in a specific credit card, eCheck or bank
2691
- #. account
2692
- msgid "You do not have any saved payment methods."
2693
  msgstr ""
2694
 
2695
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:326
2696
- #. translators: Payment method as in a specific credit card, eCheck or bank
2697
- #. account
2698
- msgid "My Payment Methods"
2699
  msgstr ""
2700
 
2701
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:334
2702
- #. translators: Payment method as in a specific credit card, e-check or bank
2703
- #. account
2704
- msgid "Add New Payment Method"
2705
  msgstr ""
2706
 
2707
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:422
2708
- msgid "Method"
 
2709
  msgstr ""
2710
 
2711
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:423
2712
- msgid "Details"
2713
  msgstr ""
2714
 
2715
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:424
2716
- msgid "Expires"
2717
  msgstr ""
2718
 
2719
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:425
2720
- msgid "Default?"
2721
  msgstr ""
2722
 
2723
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:462
2724
- msgid "Credit/Debit Cards"
 
2725
  msgstr ""
2726
 
2727
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:471
2728
- msgid "Bank Accounts"
2729
  msgstr ""
2730
 
2731
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:526
2732
- msgid "N/A"
2733
- msgstr ""
 
 
 
2734
 
2735
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:638
2736
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:199
2737
- msgid "Nickname"
2738
  msgstr ""
2739
 
2740
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:973
2741
- msgid "Oops, you took too long, please try again."
 
2742
  msgstr ""
2743
 
2744
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:986
2745
- msgid "There was an error with your request, please try again."
 
 
 
2746
  msgstr ""
2747
 
2748
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:999
2749
- #. translators: Payment method as in a specific credit card, e-check or bank
2750
- #. account
2751
- msgid "Error removing payment method"
2752
  msgstr ""
2753
 
2754
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-my-payment-methods.php:1004
2755
- #. translators: Payment method as in a specific credit card, e-check or bank
2756
- #. account
2757
- msgid "Payment method deleted."
2758
  msgstr ""
2759
 
2760
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:302
2761
- msgid "Card Number"
2762
  msgstr ""
2763
 
2764
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:323
2765
- msgid "MM / YY"
2766
  msgstr ""
2767
 
2768
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:341
2769
- msgid "Card Security Code"
2770
  msgstr ""
2771
 
2772
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:344
2773
- msgid "CSC"
2774
- msgstr ""
 
 
 
2775
 
2776
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:384
2777
- msgid "Where do I find this?"
2778
- msgstr ""
 
 
 
2779
 
2780
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:390
2781
- #. translators: e-check routing number, HTML form field label,
2782
- #. https:en.wikipedia.org/wiki/Routing_transit_number
2783
- msgid "Routing Number"
2784
- msgstr ""
 
2785
 
2786
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:409
2787
- #. translators: e-check account number, HTML form field label
2788
- msgid "Account Number"
2789
- msgstr ""
 
 
2790
 
2791
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:475
2792
- #. translators: Test mode refers to the current software environment
2793
- msgid "TEST MODE ENABLED"
2794
- msgstr ""
 
 
2795
 
2796
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:577
2797
- #. translators: Payment method as in a specific credit card, eCheck or bank
2798
- #. account
2799
- msgid "Manage Payment Methods"
2800
- msgstr ""
 
2801
 
2802
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:714
2803
- msgid "Use a new card"
2804
- msgstr ""
 
 
 
2805
 
2806
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:714
2807
- msgid "Use a new bank account"
2808
  msgstr ""
2809
 
2810
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:777
2811
- #. translators: account as in customer's account on the eCommerce site
2812
- msgid "Securely Save to Account"
2813
  msgstr ""
2814
 
2815
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:603
2816
- #. translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a>
2817
- #. tag
2818
- msgid ""
2819
- "%1$s: WooCommerce is not being forced over SSL; your customers' payment "
2820
- "data may be at risk. %2$sVerify your site URLs here%3$s"
2821
  msgstr ""
2822
 
2823
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:620
2824
- #. translators: Placeholders: %s - payment gateway name
2825
  msgid ""
2826
- "%s will soon require TLS 1.2 support to process transactions and your "
2827
- "server environment may need to be updated. Please contact your hosting "
2828
- "provider to confirm that your site can send and receive TLS 1.2 connections "
2829
- "and request they make any necessary updates."
2830
  msgstr ""
2831
 
2832
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:676
2833
- #. translators: Placeholders: %1$s - plugin name, %2$s - a
2834
- #. currency/comma-separated list of currencies, %3$s - <a> tag, %4$s - </a> tag
2835
  msgid ""
2836
- "%1$s accepts payment in %2$s only. %3$sConfigure%4$s WooCommerce to accept "
2837
- "%2$s to enable this gateway for checkout."
2838
  msgid_plural ""
2839
- "%1$s accepts payment in one of %2$s only. %3$sConfigure%4$s WooCommerce to "
2840
- "accept one of %2$s to enable this gateway for checkout."
2841
  msgstr[0] ""
2842
  msgstr[1] ""
2843
 
2844
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:711
2845
- #. translators: Placeholders: %1$s - payment gateway name, %2$s - opening <a>
2846
- #. tag, %3$s - closing </a> tag
2847
  msgid ""
2848
- "Heads up! %1$s is currently configured to log transaction data for "
2849
- "debugging purposes. If you are not experiencing any problems with payment "
2850
- "processing, we recommend %2$sturning off Debug Mode%3$s"
2851
  msgstr ""
2852
 
2853
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:750
2854
- #. translators: Placeholders: %1$s - payment gateway title (such as
2855
- #. Authorize.net, Braintree, etc), %2$s - <a> tag, %3$s - </a> tag
2856
- msgid ""
2857
- "%1$s is inactive for subscription transactions. Please %2$senable "
2858
- "tokenization%3$s to activate %1$s for Subscriptions."
2859
  msgstr ""
2860
 
2861
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:768
2862
- #. translators: Placeholders: %1$s - payment gateway title (such as
2863
- #. Authorize.net, Braintree, etc), %2$s - <a> tag, %3$s - </a> tag
2864
- msgid ""
2865
- "%1$s is inactive for pre-order transactions. Please %2$senable "
2866
- "tokenization%3$s to activate %1$s for Pre-Orders."
2867
  msgstr ""
2868
 
2869
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:805
2870
- msgid ""
2871
- "You must enable tokenization for this gateway in order to support automatic "
2872
- "renewal payments with the WooCommerce Subscriptions extension."
2873
  msgstr ""
2874
 
2875
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:806
2876
- msgid "Inactive"
 
2877
  msgstr ""
2878
 
2879
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:114
2880
- msgid "%s Customer ID"
 
2881
  msgstr ""
2882
 
2883
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:183
2884
- msgid "Type"
 
2885
  msgstr ""
2886
 
2887
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:253
2888
- msgid "Removed payment token \"%d\""
 
2889
  msgstr ""
2890
 
2891
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-privacy.php:300
2892
- msgid "Expiry Date"
2893
  msgstr ""
2894
 
2895
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:340
2896
- msgid "you successfully processed a payment!"
2897
  msgstr ""
2898
 
2899
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:345
2900
- msgid "you successfully processed a refund!"
 
2901
  msgstr ""
2902
 
2903
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:481
2904
- msgid "Check Number is missing"
 
 
 
 
2905
  msgstr ""
2906
 
2907
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:482
2908
- msgid "Drivers license state is missing"
2909
  msgstr ""
2910
 
2911
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:483
2912
- msgid "Drivers license number is missing"
2913
  msgstr ""
2914
 
2915
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:660
2916
- msgid "Place order"
2917
  msgstr ""
2918
 
2919
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:692
2920
- msgid "Thank you for your order."
2921
  msgstr ""
2922
 
2923
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1104
2924
- msgid "eCheck"
2925
  msgstr ""
2926
 
2927
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1122
2928
- msgid "Pay securely using your credit card."
2929
  msgstr ""
2930
 
2931
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1124
2932
- msgid "Pay securely using your checking account."
2933
  msgstr ""
2934
 
2935
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1270
2936
- msgid "Select the gateway environment to use for transactions."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2937
  msgstr ""
2938
 
2939
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1324
2940
- msgid "Share connection settings"
 
2941
  msgstr ""
2942
 
2943
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1326
2944
- msgid "Use connection/authentication settings from other gateway"
 
2945
  msgstr ""
2946
 
2947
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1329
2948
- msgid "Disabled because the other gateway is using these settings"
2949
- msgstr ""
 
 
 
2950
 
2951
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1346
2952
- msgid "Card Verification (CSC)"
 
 
 
 
 
 
 
 
2953
  msgstr ""
2954
 
2955
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1347
2956
- msgid "Display the Card Security Code (CV2) field on checkout"
 
 
 
 
 
 
 
2957
  msgstr ""
2958
 
2959
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1355
2960
- msgid "Saved Card Verification"
2961
  msgstr ""
2962
 
2963
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1356
2964
- msgid "Display the Card Security Code field when paying with a saved card"
 
2965
  msgstr ""
2966
 
2967
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1685
2968
- #. translators: Placeholders: %1$s - site title, %2$s - order number
2969
- msgid "%1$s - Order %2$s"
2970
  msgstr ""
2971
 
2972
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1813
2973
- #. translators: Placeholders: %1$s - site title, %2$s - order number.
2974
- #. Definitions: Capture as in capture funds from a credit card.
2975
- msgid "%1$s - Capture for Order %2$s"
2976
  msgstr ""
2977
 
2978
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:1956
2979
- #. translators: Placeholders: %1$s - site title, %2$s - order number
2980
- msgid "%1$s - Refund for Order %2$s"
2981
  msgstr ""
2982
 
2983
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2023
2984
- #. translators: Placeholders: %1$s - payment gateway title (such as
2985
- #. Authorize.net, Braintree, etc), %2$s - a monetary amount
2986
- msgid "%1$s Refund in the amount of %2$s approved."
2987
  msgstr ""
2988
 
2989
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2051
2990
- #. translators: Placeholders: %1$s - payment gateway title (such as
2991
- #. Authorize.net, Braintree, etc), %2$s - error code, %3$s - error message
2992
- msgid "%1$s Refund Failed: %2$s - %3$s"
2993
  msgstr ""
2994
 
2995
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2059
2996
- #. translators: Placeholders: %1$s - payment gateway title (such as
2997
- #. Authorize.net, Braintree, etc), %2$s - error message
2998
- msgid "%1$s Refund Failed: %2$s"
2999
  msgstr ""
3000
 
3001
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2080
3002
- #. translators: Placeholders: %s - payment gateway title (such as
3003
- #. Authorize.net, Braintree, etc)
3004
- msgid "%s Order completely refunded."
3005
  msgstr ""
3006
 
3007
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2135
3008
- msgid ""
3009
- "Oops, you cannot partially void this order. Please use the full order "
3010
- "amount."
3011
  msgstr ""
3012
 
3013
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2222
3014
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - error code,
3015
- #. %3$s - error message. Void as in to void an order.
3016
- msgid "%1$s Void Failed: %2$s - %3$s"
3017
  msgstr ""
3018
 
3019
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2230
3020
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
3021
- #. message. Void as in to void an order.
3022
- msgid "%1$s Void Failed: %2$s"
3023
  msgstr ""
3024
 
3025
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2254
3026
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - a monetary
3027
- #. amount. Void as in to void an order.
3028
- msgid "%1$s Void in the amount of %2$s approved."
3029
  msgstr ""
3030
 
3031
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2546
3032
- #. translators: Placeholders: %1$s - payment method title, %2$s - environment
3033
- #. ("Test"), %3$s - transaction type (authorization/charge)
3034
- msgid "%1$s %2$s %3$s Approved"
3035
  msgstr ""
3036
 
3037
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2556
3038
- #. translators: Placeholders: %1$s - credit card type (MasterCard, Visa,
3039
- #. etc...), %2$s - last four digits of the card
3040
- msgid "%1$s ending in %2$s"
3041
  msgstr ""
3042
 
3043
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2652
3044
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - message
3045
- #. (probably reason for the transaction being held for review)
3046
- msgid "%1$s Transaction Held for Review (%2$s)"
3047
  msgstr ""
3048
 
3049
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2741
3050
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
3051
- #. message; e.g. Order Note: [Payment method] Payment failed [error]
3052
- msgid "%1$s Payment Failed (%2$s)"
3053
  msgstr ""
3054
 
3055
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2776
3056
- #. translators: Placeholders: %1$s - payment gateway title, %2$s -
3057
- #. message/error
3058
- msgid "%1$s Transaction Cancelled (%2$s)"
3059
  msgstr ""
3060
 
3061
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3021
3062
- msgid "Transaction Type"
 
3063
  msgstr ""
3064
 
3065
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3023
3066
  msgid ""
3067
- "Select how transactions should be processed. Charge submits all "
3068
- "transactions for settlement, Authorization simply authorizes the order "
3069
- "total for capture later."
3070
  msgstr ""
3071
 
3072
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3034
3073
- msgid "Charge Virtual-Only Orders"
3074
  msgstr ""
3075
 
3076
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3036
3077
- msgid ""
3078
- "If the order contains exclusively virtual items, enable this to immediately "
3079
- "charge, rather than authorize, the transaction."
3080
  msgstr ""
3081
 
3082
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3044
3083
- msgid "Enable Partial Capture"
3084
  msgstr ""
3085
 
3086
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3046
3087
- msgid "Allow orders to be partially captured multiple times."
3088
  msgstr ""
3089
 
3090
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3058
3091
- msgid "Capture Paid Orders"
3092
  msgstr ""
3093
 
3094
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3061
3095
- msgid "Automatically capture orders when they are changed to %s."
 
 
 
 
3096
  msgstr ""
3097
 
3098
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3062
3099
- msgid "a paid status"
3100
  msgstr ""
3101
 
3102
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3252
3103
- msgid "Accepted Card Logos"
 
 
 
 
 
 
 
 
 
 
3104
  msgstr ""
3105
 
3106
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3254
3107
- msgid ""
3108
- "These are the card logos that are displayed to customers as accepted during "
3109
- "checkout."
 
3110
  msgstr ""
3111
 
3112
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3257
3113
- #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag
3114
- msgid ""
3115
- "This setting %1$sdoes not%2$s change which card types the gateway will "
3116
- "accept. Accepted cards are configured from your payment processor account."
3117
  msgstr ""
3118
 
3119
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3348
3120
- #. translators:
3121
- #. http:www.cybersource.com/products/payment_security/payment_tokenization/ and
3122
- #. https:en.wikipedia.org/wiki/Tokenization_(data_security)
3123
- msgid "Tokenization"
3124
  msgstr ""
3125
 
3126
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3349
3127
- msgid "Allow customers to securely save their payment details for future checkout."
3128
  msgstr ""
3129
 
3130
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:254
3131
- msgid "Pre-Order Tokenization attempt failed (%s)"
3132
  msgstr ""
3133
 
3134
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:300
3135
- msgid "%s - Pre-Order Release Payment for Order %s"
3136
  msgstr ""
3137
 
3138
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:304
3139
- msgid "Payment token missing/invalid."
 
3140
  msgstr ""
3141
 
3142
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:329
3143
- msgid "%s %s Pre-Order Release Payment Approved: %s ending in %s (expires %s)"
 
3144
  msgstr ""
3145
 
3146
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:340
3147
- msgid "%s eCheck Pre-Order Release Payment Approved: %s ending in %s"
 
3148
  msgstr ""
3149
 
3150
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php:382
3151
- msgid "Pre-Order Release Payment Failed: %s"
 
3152
  msgstr ""
3153
 
3154
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:213
3155
- msgid "Subscription Renewal: payment token is missing/invalid."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3156
  msgstr ""
3157
 
3158
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:239
3159
- msgid "%1$s - Subscription Renewal Order %2$s"
3160
  msgstr ""
3161
 
3162
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:371
3163
- #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
3164
- #. message; e.g. Order Note: [Payment method] Payment Change failed [error]
3165
- msgid "%1$s Payment Change Failed (%2$s)"
3166
  msgstr ""
3167
 
3168
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:511
3169
- msgid "Via %s ending in %s"
3170
  msgstr ""
3171
 
3172
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:538
3173
- msgid "Subscriptions"
3174
  msgstr ""
3175
 
3176
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:607
3177
- msgid ""
3178
- "This payment method is tied to a subscription and cannot be deleted. Please "
3179
- "switch the subscription to another method first."
3180
  msgstr ""
3181
 
3182
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:659
3183
- msgid "Payment Token"
 
3184
  msgstr ""
3185
 
3186
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:688
3187
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:693
3188
- msgid "%s is required."
3189
  msgstr ""
3190
 
3191
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php:171
3192
- msgid "Unknown Error"
3193
  msgstr ""
3194
 
3195
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:643
3196
- msgid "Job data key \"%s\" not set"
3197
  msgstr ""
3198
 
3199
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:647
3200
- msgid "Job data key \"%s\" is not an array"
3201
  msgstr ""
3202
 
3203
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:883
3204
- msgid "Every %d Minutes"
3205
  msgstr ""
3206
 
3207
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:1047
3208
- msgid "Background Processing Test"
3209
  msgstr ""
3210
 
3211
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:1048
3212
- msgid "Run Test"
3213
  msgstr ""
3214
 
3215
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:1049
3216
- msgid ""
3217
- "This tool will test whether your server is capable of processing background "
3218
- "jobs."
3219
  msgstr ""
3220
 
3221
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:1067
3222
- msgid "Success! You should be able to process background jobs."
3223
  msgstr ""
3224
 
3225
- #: vendor/skyverge/wc-plugin-framework/woocommerce/utilities/class-sv-wp-background-job-handler.php:1070
3226
  msgid ""
3227
- "Could not connect. Please ask your hosting company to ensure your server "
3228
- "has loopback connections enabled."
3229
  msgstr ""
3230
 
3231
- #: woocommerce-square.php:251
3232
- msgid ""
3233
- "Note that our next WooCommerce Square release will be a major update "
3234
- "(v3.0.0) that will include bumping the minimum PHP support from 5.6 to 7.1 "
3235
- "and migrating Square's SDK from v2.2 to v15.0.0. This will allow us to "
3236
- "provide significant enhancements into the future and while we fully test "
3237
- "all releases, please allow yourself some time and space to similarly test "
3238
- "the update before applying it to your live sites."
 
 
 
3239
  msgstr ""
3240
 
3241
  #. Plugin URI of the plugin/theme
@@ -3252,239 +3250,177 @@ msgstr ""
3252
  msgid "https://www.woocommerce.com/"
3253
  msgstr ""
3254
 
3255
- #: includes/Admin/Sync_Page.php:287
3256
  msgctxt "Delete all records"
3257
  msgid "Clear history"
3258
  msgstr ""
3259
 
3260
- #: includes/Admin/Sync_Page.php:292 includes/Admin/Sync_Page.php:333
3261
  msgctxt "Date - Time"
3262
  msgid "Time"
3263
  msgstr ""
3264
 
3265
- #: includes/Emails/Access_Token_Email.php:47
3266
  msgctxt "Email subject"
3267
  msgid "[WooCommerce] There was a problem with your Square Access Token"
3268
  msgstr ""
3269
 
3270
- #: includes/Emails/Sync_Completed.php:47
3271
  msgctxt "Email subject"
3272
  msgid "[WooCommerce] Square sync completed"
3273
  msgstr ""
3274
 
3275
- #: includes/Emails/Access_Token_Email.php:48
3276
  msgctxt "Email heading"
3277
  msgid "There was a problem with your Square Access Token"
3278
  msgstr ""
3279
 
3280
- #: includes/Emails/Access_Token_Email.php:49
3281
  msgctxt "Square connection problems email body."
3282
  msgid "Heads up! There may be a problem with your connection to Square."
3283
  msgstr ""
3284
 
3285
- #: includes/Emails/Sync_Completed.php:48
3286
  msgctxt "Email heading with merge tag placeholder"
3287
  msgid "Square sync completed for {product_count}"
3288
  msgstr ""
3289
 
3290
- #: includes/Emails/Sync_Completed.php:49
3291
  msgctxt "Email body with merge tag placeholders"
3292
  msgid ""
3293
  "Square sync completed for {site_title} at {sync_completed_date} "
3294
  "{sync_completed_time}."
3295
  msgstr ""
3296
 
3297
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php:36
3298
- msgctxt "post"
3299
- msgid "Failed"
3300
- msgstr ""
3301
-
3302
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostStatusRegistrar.php:50
3303
- msgctxt "post"
3304
- msgid "In-Progress"
3305
- msgstr ""
3306
-
3307
- #: vendor/prospress/action-scheduler/classes/ActionScheduler_wpPostStore_PostTypeRegistrar.php:32
3308
- msgctxt "Admin menu name"
3309
- msgid "Scheduled Actions"
3310
- msgstr ""
3311
-
3312
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:397
3313
- msgctxt "enhanced select"
3314
- msgid "No matches found"
3315
- msgstr ""
3316
-
3317
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:398
3318
- msgctxt "enhanced select"
3319
- msgid "Loading failed"
3320
- msgstr ""
3321
-
3322
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:399
3323
- msgctxt "enhanced select"
3324
- msgid "Please enter 1 or more characters"
3325
- msgstr ""
3326
-
3327
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:400
3328
- msgctxt "enhanced select"
3329
- msgid "Please enter %qty% or more characters"
3330
- msgstr ""
3331
-
3332
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:401
3333
- msgctxt "enhanced select"
3334
- msgid "Please delete 1 character"
3335
- msgstr ""
3336
-
3337
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:402
3338
- msgctxt "enhanced select"
3339
- msgid "Please delete %qty% characters"
3340
- msgstr ""
3341
-
3342
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:403
3343
- msgctxt "enhanced select"
3344
- msgid "You can only select 1 item"
3345
- msgstr ""
3346
-
3347
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:404
3348
- msgctxt "enhanced select"
3349
- msgid "You can only select %qty% items"
3350
- msgstr ""
3351
-
3352
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:405
3353
- msgctxt "enhanced select"
3354
- msgid "Loading more results&hellip;"
3355
- msgstr ""
3356
-
3357
- #: vendor/skyverge/wc-plugin-framework/woocommerce/admin/abstract-sv-wc-plugin-admin-setup-wizard.php:406
3358
- msgctxt "enhanced select"
3359
- msgid "Searching&hellip;"
3360
- msgstr ""
3361
-
3362
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-helper.php:408
3363
- msgctxt "coordinating conjunction for a list of items: a, b, and c"
3364
- msgid "and"
3365
- msgstr ""
3366
-
3367
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:534
3368
- msgctxt "noun"
3369
- msgid "Support"
3370
  msgstr ""
3371
 
3372
- #: vendor/skyverge/wc-plugin-framework/woocommerce/class-sv-wc-plugin.php:539
3373
- msgctxt "verb"
3374
- msgid "Review"
3375
  msgstr ""
3376
 
3377
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:736
3378
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2548
3379
  msgctxt "noun, software environment"
3380
  msgid "Test"
3381
  msgstr ""
3382
 
3383
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:737
3384
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2549
3385
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3027
3386
  msgctxt "credit card transaction type"
3387
  msgid "Authorization"
3388
  msgstr ""
3389
 
3390
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php:737
3391
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2549
3392
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3026
3393
  msgctxt "noun, credit card transaction type"
3394
  msgid "Charge"
3395
  msgstr ""
3396
 
3397
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:192
3398
- msgctxt "payment method type"
3399
- msgid "Account"
 
 
3400
  msgstr ""
3401
 
3402
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:228
3403
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3285
3404
  msgctxt "credit card type"
3405
  msgid "Visa"
3406
  msgstr ""
3407
 
3408
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:232
3409
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3286
3410
  msgctxt "credit card type"
3411
  msgid "MasterCard"
3412
  msgstr ""
3413
 
3414
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:236
3415
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3287
3416
  msgctxt "credit card type"
3417
  msgid "American Express"
3418
  msgstr ""
3419
 
3420
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:240
 
3421
  msgctxt "credit card type"
3422
- msgid "Diners Club"
3423
  msgstr ""
3424
 
3425
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:244
3426
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3288
3427
  msgctxt "credit card type"
3428
- msgid "Discover"
3429
  msgstr ""
3430
 
3431
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:248
3432
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3290
3433
  msgctxt "credit card type"
3434
  msgid "JCB"
3435
  msgstr ""
3436
 
3437
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:252
 
 
 
 
 
3438
  msgctxt "credit card type"
3439
  msgid "CarteBleue"
3440
  msgstr ""
3441
 
3442
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:256
3443
  msgctxt "credit card type"
3444
  msgid "Maestro"
3445
  msgstr ""
3446
 
3447
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-helper.php:260
3448
  msgctxt "credit card type"
3449
  msgid "Laser"
3450
  msgstr ""
3451
 
3452
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3289
3453
- msgctxt "credit card type"
3454
- msgid "Diners"
3455
  msgstr ""
3456
 
3457
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:435
3458
- #. translators: http:www.investopedia.com/terms/c/checkingaccount.asp
3459
- msgctxt "account type"
3460
- msgid "Checking"
3461
  msgstr ""
3462
 
3463
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php:437
3464
- #. translators: http:www.investopedia.com/terms/s/savingsaccount.asp
3465
- msgctxt "account type"
3466
- msgid "Savings"
3467
  msgstr ""
3468
 
3469
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:2329
3470
- msgctxt "hash before order number"
3471
- msgid "#"
3472
  msgstr ""
3473
 
3474
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php:568
3475
- msgctxt "hash before order number"
3476
- msgid "#%s"
 
3477
  msgstr ""
3478
 
3479
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3055
3480
- msgctxt ""
3481
- "coordinating conjunction for a list of order statuses: on-hold, processing, "
3482
- "or completed"
3483
- msgid "or"
3484
  msgstr ""
3485
 
3486
- #: vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php:3891
3487
- #. translators: https:www.skyverge.com/for-translators-environments/
3488
- msgctxt "software environment"
3489
- msgid "Production"
 
 
 
 
3490
  msgstr ""
2
  # This file is distributed under the GNU General Public License v3.0.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WooCommerce Square 3.0.0\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-square\n"
8
+ "POT-Creation-Date: 2022-05-05 00:39:11+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
14
  "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
15
  "X-Generator: grunt-wp-i18n 1.0.3\n"
16
 
17
+ #: includes/AJAX.php:75
18
  msgid "Please mark product as un-synced and save, then synced again."
19
  msgstr ""
20
 
21
+ #: includes/AJAX.php:88
22
  #. translators: Placeholders: %1$s = error message, %2$s = help text
23
  msgid "Unable to fetch inventory: %1$s. %2$s"
24
  msgstr ""
25
 
26
+ #: includes/AJAX.php:93
27
  #. translators: Placeholders: %s = help text
28
  msgid "Error finding item in Square. %s"
29
  msgstr ""
30
 
31
+ #: includes/AJAX.php:111
32
  msgid "Could not start import. Please try again."
33
  msgstr ""
34
 
35
+ #: includes/AJAX.php:114
36
  msgid ""
37
  "Your products are being imported in the background! This may take some time "
38
  "to complete."
39
  msgstr ""
40
 
41
+ #: includes/AJAX.php:160
42
  msgid "Could not delete records."
43
  msgstr ""
44
 
45
+ #: includes/AJAX.php:168
46
  msgid "Could not delete record."
47
  msgstr ""
48
 
49
+ #: includes/AJAX.php:178
50
  msgid "Could not resolve record."
51
  msgstr ""
52
 
53
+ #: includes/AJAX.php:190
54
  msgid "Could not unsync product."
55
  msgstr ""
56
 
57
+ #: includes/AJAX.php:202
58
  #. translators: Placeholder: %s - error message
59
  msgid "An error occurred. %s"
60
  msgstr ""
61
 
62
+ #: includes/AJAX.php:247
63
  #. translators: Placeholder: %s - sync job ID
64
  msgid "No sync job in progress found %s"
65
  msgstr ""
66
 
67
+ #: includes/AJAX.php:285
68
  msgid "Stock must be fetched from Square before editing stock quantity"
69
  msgstr ""
70
 
71
+ #: includes/Admin/Privacy.php:43 includes/Admin/Settings_Page.php:54
72
+ #: includes/Gateway.php:82 includes/Settings.php:221 includes/Settings.php:755
73
  msgid "Square"
74
  msgstr ""
75
 
76
+ #: includes/Admin/Privacy.php:45
77
  msgid "WooCommerce Square Customer Data"
78
  msgstr ""
79
 
80
+ #: includes/Admin/Privacy.php:59
81
  #. translators: Placeholder: %1$s - <a> tag, %2$s - </a> tag
82
  msgid ""
83
  "By using this extension, you may be storing personal data or sharing data "
85
  "what you may want to include in your privacy policy.%2$s"
86
  msgstr ""
87
 
88
+ #: includes/Admin/Privacy.php:91
89
  msgid "Square User Data Erased."
90
  msgstr ""
91
 
92
+ #: includes/Admin/Settings_Page.php:144
93
  msgid "Settings"
94
  msgstr ""
95
 
96
+ #: includes/Admin/Settings_Page.php:145 includes/Admin/Sync_Page.php:49
97
  msgid "Update"
98
  msgstr ""
99
 
100
+ #: includes/Admin/Settings_Page.php:172
101
  msgid "Import Products From Square"
102
  msgstr ""
103
 
104
+ #: includes/Admin/Settings_Page.php:174 includes/Admin/Sync_Page.php:358
105
  msgid "Close modal window"
106
  msgstr ""
107
 
108
+ #: includes/Admin/Settings_Page.php:179
109
  #. translators: Placeholders: %1$s - <strong>, %2%s - </strong>
110
  msgid ""
111
  "You are about to import all new products, variations and categories from "
114
  "imports, these will be ignored in the import."
115
  msgstr ""
116
 
117
+ #: includes/Admin/Settings_Page.php:181
118
  msgid "Do you wish to import existing product updates from Square?"
119
  msgstr ""
120
 
121
+ #: includes/Admin/Settings_Page.php:183
122
  #. translators: Placeholders: %1$s - <a> tag linking to WooCommerce Square
123
  #. docs, %2%s - closing </a> tag
124
  msgid ""
126
  "information from Square. %1$sView Documentation%2$s."
127
  msgstr ""
128
 
129
+ #: includes/Admin/Settings_Page.php:184
130
  msgid "Update existing products during import."
131
  msgstr ""
132
 
133
+ #: includes/Admin/Settings_Page.php:188 includes/Admin/Sync_Page.php:392
134
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:41
135
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:203
136
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:133
137
  msgid "Cancel"
138
  msgstr ""
139
 
140
+ #: includes/Admin/Settings_Page.php:189 includes/Settings.php:242
141
  msgid "Import Products"
142
  msgstr ""
143
 
144
+ #: includes/Admin/Sync_Page.php:53
145
  msgid "Sync records"
146
  msgstr ""
147
 
148
+ #: includes/Admin/Sync_Page.php:79
149
  #. translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s,
150
  #. $4%s - closing </strong> HTML tag
151
  msgid ""
154
  "description, category, inventory%4$s."
155
  msgstr ""
156
 
157
+ #: includes/Admin/Sync_Page.php:93
158
  #. translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing
159
  #. </strong> HTML tag
160
  msgid ""
162
  "set in WooCommerce."
163
  msgstr ""
164
 
165
+ #: includes/Admin/Sync_Page.php:108
166
  #. translators: Placeholders: %1$s, %3$s - opening <strong> HTML tag, %2$s,
167
  #. %4$s - closing </strong> HTML tag
168
  msgid ""
171
  "price, inventory, category, image%4$s."
172
  msgstr ""
173
 
174
+ #: includes/Admin/Sync_Page.php:125
175
  #. translators: Placeholders: %1$s - opening <strong> HTML tag, %2$s closing
176
  #. </strong> HTML tag
177
  msgid ""
179
  "Square and WooCommerce."
180
  msgstr ""
181
 
182
+ #: includes/Admin/Sync_Page.php:160
183
  msgid "Please connect to Square to enable product sync."
184
  msgstr ""
185
 
186
+ #: includes/Admin/Sync_Page.php:162
187
  msgid "Please set the business location to enable product sync."
188
  msgstr ""
189
 
190
+ #: includes/Admin/Sync_Page.php:164
191
  msgid "There are currently no products marked to be synced with Square."
192
  msgstr ""
193
 
194
+ #: includes/Admin/Sync_Page.php:166
195
  msgid "A sync is currently in progress. Please try again later."
196
  msgstr ""
197
 
198
+ #: includes/Admin/Sync_Page.php:171
199
  #. translators: Placeholder: %s - reason text
200
  msgid "Product sync between WooCommerce and Square is currently unavailable. %s"
201
  msgstr ""
202
 
203
+ #: includes/Admin/Sync_Page.php:178
204
  msgid "Synced products"
205
  msgstr ""
206
 
207
+ #: includes/Admin/Sync_Page.php:179
208
  msgid "Latest sync"
209
  msgstr ""
210
 
211
+ #: includes/Admin/Sync_Page.php:180
212
  msgid "Next sync"
213
  msgstr ""
214
 
215
+ #: includes/Admin/Sync_Page.php:181 includes/Admin/Sync_Page.php:294
216
+ #: includes/Admin/Sync_Page.php:335
217
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:315
218
  msgid "Actions"
219
  msgstr ""
220
 
221
+ #: includes/Admin/Sync_Page.php:191 includes/Emails/Sync_Completed.php:195
222
  #. translators: Placeholder: %d number of products synced with Square
223
  #. translators: Placeholder: %d products count
224
  msgid "%d product"
226
  msgstr[0] ""
227
  msgstr[1] ""
228
 
229
+ #: includes/Admin/Sync_Page.php:209
230
  msgid "Importing now&hellip;"
231
  msgstr ""
232
 
233
+ #: includes/Admin/Sync_Page.php:211
234
  msgid "Syncing now&hellip;"
235
  msgstr ""
236
 
237
+ #: includes/Admin/Sync_Page.php:226
238
  msgid "Not synced yet."
239
  msgstr ""
240
 
241
+ #: includes/Admin/Sync_Page.php:258
242
  msgid "Sync now"
243
  msgstr ""
244
 
245
+ #: includes/Admin/Sync_Page.php:292 includes/Admin/Sync_Page.php:333
246
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:144
247
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:97
248
  msgid "Status"
249
  msgstr ""
250
 
251
+ #: includes/Admin/Sync_Page.php:293 includes/Admin/Sync_Page.php:334
252
  msgid "Message"
253
  msgstr ""
254
 
255
+ #: includes/Admin/Sync_Page.php:324
256
  msgid "No records found."
257
  msgstr ""
258
 
259
+ #: includes/Admin/Sync_Page.php:356
260
  msgid "Sync products with Square"
261
  msgstr ""
262
 
263
+ #: includes/Admin/Sync_Page.php:366
264
  msgid ""
265
  "If a match is found in Square, product data in WooCommerce will be "
266
  "overwritten with Square data."
267
  msgstr ""
268
 
269
+ #: includes/Admin/Sync_Page.php:368
270
  msgid ""
271
  "If a match is found in WooCommerce, product data in Square will be "
272
  "overwritten with WooCommerce data."
273
  msgstr ""
274
 
275
+ #: includes/Admin/Sync_Page.php:372
276
  msgid ""
277
  "If a match is not found in Square, the product will be hidden from the "
278
  "catalog in WooCommerce."
279
  msgstr ""
280
 
281
+ #: includes/Admin/Sync_Page.php:374
282
  msgid "If a match is not found in Square, the product will be skipped in the sync."
283
  msgstr ""
284
 
285
+ #: includes/Admin/Sync_Page.php:377
286
  msgid "If a match is not found, a new product will be created in Square."
287
  msgstr ""
288
 
289
+ #: includes/Admin/Sync_Page.php:384
290
  #. translators: Placeholders: %1$s - the system of record name (e.g. Square or
291
  #. WooCommerce), %3%s - unordered HTML list of additional information item(s)
292
  msgid ""
294
  "For all products synced with Square: %2$s"
295
  msgstr ""
296
 
297
+ #: includes/Admin/Sync_Page.php:393
298
  msgid "Start sync"
299
  msgstr ""
300
 
301
+ #: includes/Admin.php:143 includes/Handlers/Products.php:175
302
  msgid "Synced with Square"
303
  msgstr ""
304
 
310
  msgid "Fetch stock from Square"
311
  msgstr ""
312
 
313
+ #: includes/Admin.php:191 includes/Sync/Records/Record.php:208
314
  msgid "Resolved"
315
  msgstr ""
316
 
317
+ #: includes/Admin.php:192
318
  msgid "No records found"
319
  msgstr ""
320
 
321
+ #: includes/Admin.php:193
322
  msgid "Skipped"
323
  msgstr ""
324
 
325
+ #: includes/Admin.php:194
326
  msgid "Updated"
327
  msgstr ""
328
 
329
+ #: includes/Admin.php:195
330
  msgid "Imported"
331
  msgstr ""
332
 
333
+ #: includes/Admin.php:197
334
  msgid "Enable to fetch inventory changes from Square"
335
  msgstr ""
336
 
337
+ #: includes/Admin.php:198
338
  msgid "Enable to push inventory changes to Square"
339
  msgstr ""
340
 
341
+ #: includes/Admin.php:201 includes/Settings.php:231
342
  msgid "Inventory is fetched from Square periodically and updated in WooCommerce"
343
  msgstr ""
344
 
345
+ #: includes/Admin.php:204
346
  #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag
347
  msgid ""
348
  "Inventory is %1$salways fetched from Square%2$s periodically to account for "
349
  "sales from other channels."
350
  msgstr ""
351
 
352
+ #: includes/Emails/Access_Token_Email.php:43
353
  msgid "Square Access Token problems"
354
  msgstr ""
355
 
356
+ #: includes/Emails/Access_Token_Email.php:44
357
  msgid "This email is sent when problems with Access Token are encountered"
358
  msgstr ""
359
 
360
+ #: includes/Emails/Access_Token_Email.php:97
361
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
362
  #. </a> HTML link tag
363
  msgid ""
365
  "re-connect your site%2$s."
366
  msgstr ""
367
 
368
+ #: includes/Emails/Access_Token_Email.php:105
369
+ #: includes/Emails/Sync_Completed.php:88
370
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
371
  #. </a> HTML link tag
372
  msgid "%1$sInspect status logs%2$s"
373
  msgstr ""
374
 
375
+ #: includes/Emails/Access_Token_Email.php:111
376
  msgid ""
377
  "In order to continue accepting payments, please disconnect and re-connect "
378
  "your site at "
395
  "%s"
396
  msgstr ""
397
 
398
+ #: includes/Emails/Sync_Completed.php:33
399
  msgid "Square sync completed"
400
  msgstr ""
401
 
402
+ #: includes/Emails/Sync_Completed.php:34
403
  msgid ""
404
  "This email is sent once a manual sync has been completed between "
405
  "WooCommerce and Square"
406
  msgstr ""
407
 
408
+ #: includes/Emails/Sync_Completed.php:58
409
  msgid "Square sync failed"
410
  msgstr ""
411
 
412
+ #: includes/Emails/Sync_Completed.php:95
413
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
414
  #. </a> HTML link tag
415
  msgid "%1$sEnable logging%2$s"
416
  msgstr ""
417
 
418
+ #: includes/Emails/Sync_Completed.php:103
419
  #. translators: Placeholders: %1$s - opening <a> HTML link tag, %2$s - closing
420
  #. </a> HTML link tag, %3$s - additional action
421
  msgid "The sync job has failed. %1$sClick for more details%2$s, or %3$s."
422
  msgstr ""
423
 
424
+ #: includes/Emails/Sync_Completed.php:112
425
  msgid "Inspect status logs"
426
  msgstr ""
427
 
428
+ #: includes/Emails/Sync_Completed.php:114 includes/Settings.php:267
429
  msgid "Enable Logging"
430
  msgstr ""
431
 
432
+ #: includes/Emails/Sync_Completed.php:119
433
  #. translators: Placeholders: %s - additional action
434
  msgid "The sync job has failed. Check sync records, or %s."
435
  msgstr ""
436
 
437
+ #: includes/Framework/Lifecycle.php:303 includes/Lifecycle.php:183
438
+ msgid "Awesome"
 
 
439
  msgstr ""
440
 
441
+ #: includes/Framework/Lifecycle.php:304 includes/Lifecycle.php:186
442
+ msgid "Fantastic"
 
443
  msgstr ""
444
 
445
+ #: includes/Framework/Lifecycle.php:305
446
+ msgid "Cowabunga"
 
 
 
 
 
447
  msgstr ""
448
 
449
+ #: includes/Framework/Lifecycle.php:306 includes/Lifecycle.php:184
450
+ msgid "Congratulations"
 
451
  msgstr ""
452
 
453
+ #: includes/Framework/Lifecycle.php:307
454
+ msgid "Hot dog"
 
 
 
 
 
455
  msgstr ""
456
 
457
+ #: includes/Framework/Lifecycle.php:314 includes/Lifecycle.php:193
458
+ #. translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a>
459
+ #. tag, %4$s - <a> tag, %5$s - </a> tag
460
  msgid ""
461
+ "Are you having a great experience with %1$s so far? Please consider "
462
+ "%2$sleaving a review%3$s! If things aren't going quite as expected, we're "
463
+ "happy to help -- please %4$sreach out to our support team%5$s."
464
  msgstr ""
465
 
466
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:100
467
+ msgid "Are you sure you wish to process this capture? The action cannot be undone."
 
 
 
 
 
 
468
  msgstr ""
469
 
470
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:103
471
+ msgid ""
472
+ "Something went wrong, and the capture could no be completed. Please try "
473
+ "again."
474
  msgstr ""
475
 
476
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:147
477
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:265
478
+ msgid "Capture Charge"
479
  msgstr ""
480
 
481
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:255
482
+ msgid "This charge has been fully captured."
 
 
 
483
  msgstr ""
484
 
485
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:257
486
+ msgid "This charge can no longer be captured."
 
487
  msgstr ""
488
 
489
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php:259
490
+ msgid "This charge cannot be captured."
 
491
  msgstr ""
492
 
493
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:71
494
+ msgid "Are you sure you want to remove this token?"
495
  msgstr ""
496
 
497
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:81
498
+ msgid "Invalid token data"
 
499
  msgstr ""
500
 
501
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:85
502
+ msgid "An error occurred. Please try again."
 
503
  msgstr ""
504
 
505
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:433
506
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_User_Handler.php:279
507
+ msgid "(%s)"
508
  msgstr ""
509
 
510
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:463
511
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:537
512
+ msgid "Default"
513
  msgstr ""
514
 
515
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:499
516
+ msgid "Token ID"
517
  msgstr ""
518
 
519
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:504
520
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:274
521
+ msgid "Card Type"
522
  msgstr ""
523
 
524
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:509
525
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:166
526
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:272
527
+ msgid "Last Four"
528
  msgstr ""
529
 
530
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:516
531
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:286
532
+ msgid "Expiration (MM/YY)"
533
  msgstr ""
534
 
535
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:614
536
+ msgid "Refresh"
537
  msgstr ""
538
 
539
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:616
540
+ msgid "Add New"
 
 
541
  msgstr ""
542
 
543
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:619
544
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:632
545
+ msgid "Save"
 
546
  msgstr ""
547
 
548
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php:642
549
+ msgid "Remove"
 
550
  msgstr ""
551
 
552
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_User_Handler.php:198
553
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:35
554
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:36
555
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:183
556
+ msgid "%s Payment Tokens"
557
  msgstr ""
558
 
559
+ #: includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_User_Handler.php:276
560
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:640
561
+ msgid "Customer ID"
562
  msgstr ""
563
 
564
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:7
565
+ msgid "This section contains configuration settings for this gateway."
 
566
  msgstr ""
567
 
568
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:28
569
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1195
570
+ #. translators: environment as in a software environment (test/production)
571
+ msgid "Environment"
572
  msgstr ""
573
 
574
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:29
575
+ msgid "The transaction environment for this gateway."
576
  msgstr ""
577
 
578
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:36
579
+ msgid "Tokenization Enabled"
 
580
  msgstr ""
581
 
582
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:37
583
+ msgid "Displays whether or not tokenization is enabled for this gateway."
 
 
 
584
  msgstr ""
585
 
586
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:50
587
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1125
588
+ #: includes/Gateway.php:645
589
  msgid "Debug Mode"
590
  msgstr ""
591
 
592
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:51
593
+ msgid "Displays whether or not debug logging is enabled for this gateway."
 
 
 
 
594
  msgstr ""
595
 
596
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:54
597
+ msgid "Display at Checkout & Log"
 
 
598
  msgstr ""
599
 
600
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:56
601
+ msgid "Display at Checkout"
 
602
  msgstr ""
603
 
604
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:58
605
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1133
606
+ #: includes/Gateway.php:653
607
  msgid "Save to Log"
608
  msgstr ""
609
 
610
+ #: includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php:60
611
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1131
612
+ #: includes/Gateway.php:651
613
+ msgid "Off"
614
  msgstr ""
615
 
616
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:5
617
+ msgid "Authorization total"
618
  msgstr ""
619
 
620
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:9
621
+ msgid "Amount already captured"
 
 
622
  msgstr ""
623
 
624
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:15
625
+ msgid "Remaining order total"
626
  msgstr ""
627
 
628
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:21
629
+ msgid "Capture amount"
630
  msgstr ""
631
 
632
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:28
633
+ msgid "Comment (optional):"
 
 
 
 
634
  msgstr ""
635
 
636
+ #: includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php:40
637
+ msgid "Capture %s"
638
  msgstr ""
639
 
640
+ #: includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor-token.php:23
641
+ msgid "-- Select an option --"
642
  msgstr ""
643
 
644
+ #: includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor.php:34
645
+ msgid "No saved payment tokens"
 
 
 
646
  msgstr ""
647
 
648
+ #: includes/Framework/PaymentGateway/Admin/views/html-user-profile-field-customer-id.php:5
649
+ msgid "The gateway customer ID for the user. Only edit this if necessary."
650
  msgstr ""
651
 
652
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:33
653
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php:118
654
+ msgid "An error occurred, please try again or try an alternate form of payment"
655
  msgstr ""
656
 
657
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:34
658
+ msgid ""
659
+ "We cannot process your order with the payment information that you "
660
+ "provided. Please use a different payment account or an alternate payment "
661
+ "method."
662
  msgstr ""
663
 
664
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:35
665
+ msgid ""
666
+ "This order is being placed on hold for review. Please contact us to "
667
+ "complete the transaction."
668
  msgstr ""
669
 
670
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:40
671
+ msgid ""
672
+ "This order is being placed on hold for review due to an incorrect card "
673
+ "verification number. You may contact the store to complete the transaction."
674
  msgstr ""
675
 
676
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:41
677
+ msgid "The card verification number is invalid, please try again."
678
  msgstr ""
679
 
680
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:42
681
+ msgid "Please enter your card verification number and try again."
682
+ msgstr ""
683
+
684
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:45
685
  msgid ""
686
+ "That card type is not accepted, please use an alternate card or other form "
687
+ "of payment."
688
  msgstr ""
689
 
690
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:46
691
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:50
692
+ msgid ""
693
+ "The card type is invalid or does not correlate with the credit card number. "
694
+ " Please try again or use an alternate card or other form of payment."
695
  msgstr ""
696
 
697
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:47
698
+ msgid "Please select the card type and try again."
699
  msgstr ""
700
 
701
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:51
702
+ msgid "The card number is invalid, please re-enter and try again."
703
  msgstr ""
704
 
705
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:52
706
+ msgid "Please enter your card number and try again."
707
  msgstr ""
708
 
709
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:55
710
+ msgid "The card expiration date is invalid, please re-enter and try again."
711
  msgstr ""
712
 
713
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:56
714
+ msgid "The card expiration month is invalid, please re-enter and try again."
715
  msgstr ""
716
 
717
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:57
718
+ msgid "The card expiration year is invalid, please re-enter and try again."
719
  msgstr ""
720
 
721
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:58
722
+ msgid "Please enter your card expiration date and try again."
723
  msgstr ""
724
 
725
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:61
726
+ msgid "The bank routing number is invalid, please re-enter and try again."
727
  msgstr ""
728
 
729
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:62
730
+ msgid "The bank account number is invalid, please re-enter and try again."
731
  msgstr ""
732
 
733
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:65
 
734
  msgid ""
735
+ "The provided card is expired, please use an alternate card or other form of "
736
+ "payment."
737
  msgstr ""
738
 
739
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:66
740
+ msgid ""
741
+ "The provided card was declined, please use an alternate card or other form "
742
+ "of payment."
743
  msgstr ""
744
 
745
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:67
 
746
  msgid ""
747
+ "Insufficient funds in account, please use an alternate card or other form "
748
+ "of payment."
749
  msgstr ""
750
 
751
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:68
 
752
  msgid ""
753
+ "The card is inactivate or not authorized for card-not-present transactions, "
754
+ "please use an alternate card or other form of payment."
 
755
  msgstr ""
756
 
757
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:69
758
+ msgid ""
759
+ "The credit limit for the card has been reached, please use an alternate "
760
+ "card or other form of payment."
761
  msgstr ""
762
 
763
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:70
764
+ msgid "The card verification number does not match. Please re-enter and try again."
765
  msgstr ""
766
 
767
+ #: includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php:71
768
+ msgid ""
769
+ "The provided address does not match the billing address for cardholder. "
770
+ "Please verify the address and try again."
771
  msgstr ""
772
 
773
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:102
774
+ msgid "Invalid payment response data"
775
  msgstr ""
776
 
777
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:105
778
+ msgid ""
779
+ "Payment Response:\n"
780
+ " %s"
781
  msgstr ""
782
 
783
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:113
784
+ msgid "Apple Pay payment authorized."
785
  msgstr ""
786
 
787
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:129
788
+ msgid "Gateway processing error."
789
  msgstr ""
790
 
791
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:146
792
+ msgid "Apple Pay payment failed. %s"
793
  msgstr ""
794
 
795
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:226
796
+ msgid "Not available for subscription products."
797
  msgstr ""
798
 
799
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:231
800
+ msgid "Not available for pre-order products that are set to charge upon release."
 
 
 
 
 
801
  msgstr ""
802
 
803
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:236
804
+ msgid "Buy Now is only available for simple products"
 
 
 
 
 
 
 
 
805
  msgstr ""
806
 
807
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:241
808
+ msgid "Product is not available for purchase."
 
809
  msgstr ""
810
 
811
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:287
812
+ msgid "Cart contains subscriptions."
813
  msgstr ""
814
 
815
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:291
816
+ msgid "Cart contains pre-orders."
 
817
  msgstr ""
818
 
819
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:301
820
+ msgid "Apple Pay cannot be used for multiple shipments."
 
 
 
 
 
 
821
  msgstr ""
822
 
823
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:336
824
+ msgid "Payment request data is missing."
 
 
 
825
  msgstr ""
826
 
827
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:345
828
+ msgid "Cart data is missing."
829
  msgstr ""
830
 
831
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:531
832
+ msgid "Subtotal"
833
  msgstr ""
834
 
835
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:541
836
+ #: includes/Gateway/API/Requests/Orders.php:77
837
+ #: includes/Gateway/Digital_Wallet.php:426
838
+ msgid "Discount"
839
  msgstr ""
840
 
841
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:551
842
+ #: includes/Gateway/Digital_Wallet.php:410
843
+ msgid "Shipping"
844
  msgstr ""
845
 
846
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:561
847
+ #: includes/Gateway/Digital_Wallet.php:434
848
+ msgid "Fees"
 
 
 
849
  msgstr ""
850
 
851
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php:571
852
+ msgid "Taxes"
 
 
 
 
853
  msgstr ""
854
 
855
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:71
856
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:89
857
+ msgid "Apple Pay"
 
 
858
  msgstr ""
859
 
860
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:95
861
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1071
862
+ #: includes/Gateway.php:586 includes/Gateway.php:756
863
+ msgid "Enable / Disable"
864
  msgstr ""
865
 
866
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:96
867
+ msgid "Accept Apple Pay"
 
868
  msgstr ""
869
 
870
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:103
871
+ msgid "Allow Apple Pay on"
 
872
  msgstr ""
873
 
874
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:113
875
+ msgid "Button Style"
 
 
 
 
 
 
 
876
  msgstr ""
877
 
878
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:116
879
+ msgid "Black"
 
 
 
 
 
880
  msgstr ""
881
 
882
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:117
883
+ msgid "White"
 
 
 
 
 
884
  msgstr ""
885
 
886
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:118
887
+ msgid "White with outline"
 
 
 
 
888
  msgstr ""
889
 
890
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:130
891
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1246
892
+ msgid "Connection Settings"
 
 
893
  msgstr ""
894
 
895
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:136
896
+ msgid "Apple Merchant ID"
 
 
 
 
897
  msgstr ""
898
 
899
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:140
900
+ msgid "This is found in your %1$sApple developer account%2$s"
901
  msgstr ""
902
 
903
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:147
904
+ msgid "Certificate Path"
 
 
 
905
  msgstr ""
906
 
907
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:149
908
  msgid ""
909
+ "The full system path to your certificate file from Apple. For security "
910
+ "reasons you should store this outside of your web root."
911
  msgstr ""
912
 
913
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:152
914
+ #. translators: Placeholders: %s - the server's web root path
915
+ msgid "For reference, your current web root path is: %s"
916
  msgstr ""
917
 
918
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:165
919
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:175
920
+ msgid "Processing Gateway"
921
  msgstr ""
922
 
923
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:183
924
+ msgid "Test Mode"
 
 
925
  msgstr ""
926
 
927
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:184
928
+ msgid ""
929
+ "Enable to test Apple Pay functionality throughout your sites without "
930
+ "processing real payments."
931
  msgstr ""
932
 
933
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:293
934
+ msgid "Your site must be served over HTTPS with a valid SSL certificate."
 
935
  msgstr ""
936
 
937
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:303
938
+ #. translators: Placeholders: %1$s - plugin name, %2$s - a
939
+ #. currency/comma-separated list of currencies, %3$s - <a> tag, %4$s - </a> tag
940
+ msgid ""
941
+ "Accepts payment in %1$s only. %2$sConfigure%3$s WooCommerce to accept %1$s "
942
+ "to enable Apple Pay."
943
+ msgid_plural ""
944
+ "Accepts payment in one of %1$s only. %2$sConfigure%3$s WooCommerce to "
945
+ "accept one of %1$s to enable Apple Pay."
946
+ msgstr[0] ""
947
+ msgstr[1] ""
948
 
949
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:322
950
  msgid ""
951
+ "Your %1$sMerchant Identity Certificate%2$s cannot be found. Please check "
952
+ "your path configuration."
953
  msgstr ""
954
 
955
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:329
956
+ msgid "Apple Pay is disabled."
957
  msgstr ""
958
 
959
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:368
960
+ msgid "Single products"
 
 
 
 
961
  msgstr ""
962
 
963
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:369
964
+ msgid "Cart"
965
  msgstr ""
966
 
967
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php:370
968
+ msgid "Checkout"
 
 
 
 
 
969
  msgstr ""
970
 
971
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Ajax.php:117
972
+ msgid "Could not validate merchant. %s"
973
  msgstr ""
974
 
975
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php:155
976
+ msgid "Buy with"
 
 
 
 
 
977
  msgstr ""
978
 
979
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php:186
980
+ msgid "Product does not exist."
981
  msgstr ""
982
 
983
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php:289
984
+ msgid "Pay with"
985
  msgstr ""
986
 
987
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php:295
988
+ msgid "or"
989
  msgstr ""
990
 
991
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:72
992
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:79
993
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:92
994
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:101
995
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:113
996
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:157
997
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:167
998
+ #: includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php:169
999
+ msgid "Error %d: Unable to create order. Please try again."
1000
  msgstr ""
1001
 
1002
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:136
1003
+ msgid "Order cannot be captured"
1004
  msgstr ""
1005
 
1006
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:141
1007
+ msgid "Transaction authorization has expired"
1008
  msgstr ""
1009
 
1010
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:146
1011
+ msgid "Transaction has already been fully captured"
 
 
1012
  msgstr ""
1013
 
1014
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:151
1015
+ msgid "Transaction cannot be captured"
 
 
 
1016
  msgstr ""
1017
 
1018
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:167
1019
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1020
+ #. Authorize.net, Braintree, etc), %2$s - transaction amount. Definitions:
1021
+ #. Capture, as in capture funds from a credit card.
1022
+ msgid "%1$s Capture of %2$s Approved"
1023
  msgstr ""
1024
 
1025
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:174
1026
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:311
1027
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1873
1028
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2087
1029
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2387
1030
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:584
1031
+ #. translators: Placeholders: %s - transaction ID
1032
+ msgid "(Transaction ID %s)"
1033
  msgstr ""
1034
 
1035
+ #: includes/Framework/PaymentGateway/Handlers/Capture.php:205
1036
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1037
+ #. Authorize.net, Braintree, etc), %2$s - failure message. Definitions:
1038
+ #. "capture" as in capturing funds from a credit card.
1039
+ msgid "%1$s Capture Failed: %2$s"
1040
  msgstr ""
1041
 
1042
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:226
1043
+ msgid "Pre-Order Tokenization attempt failed (%s)"
1044
  msgstr ""
1045
 
1046
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:272
1047
+ msgid "%s - Pre-Order Release Payment for Order %s"
 
 
 
 
 
 
 
 
1048
  msgstr ""
1049
 
1050
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:276
1051
+ msgid "Payment token missing/invalid."
 
1052
  msgstr ""
1053
 
1054
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:299
1055
+ msgid "%s %s Pre-Order Release Payment Approved: %s ending in %s (expires %s)"
 
 
1056
  msgstr ""
1057
 
1058
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:328
1059
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1610
1060
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:678
1061
+ #. translators: This is a message describing that the transaction in question
1062
+ #. only performed a credit card authorization and did not capture any funds.
1063
+ msgid "Authorization only transaction"
1064
  msgstr ""
1065
 
1066
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php:347
1067
+ msgid "Pre-Order Release Payment Failed: %s"
1068
  msgstr ""
1069
 
1070
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:193
1071
+ msgid "Subscription Renewal: payment token is missing/invalid."
1072
  msgstr ""
1073
 
1074
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:219
1075
+ msgid "%1$s - Subscription Renewal Order %2$s"
1076
  msgstr ""
1077
 
1078
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:348
1079
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
1080
+ #. message; e.g. Order Note: [Payment method] Payment Change failed [error]
1081
+ msgid "%1$s Payment Change Failed (%2$s)"
1082
  msgstr ""
1083
 
1084
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:353
1085
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2523
1086
+ #: includes/Gateway/Blocks_Handler.php:137
1087
+ #: includes/Gateway/Digital_Wallet.php:208
1088
+ #: includes/Gateway/Payment_Form.php:238 includes/Gateway.php:251
1089
+ msgid "An error occurred, please try again or try an alternate form of payment."
1090
  msgstr ""
1091
 
1092
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:488
1093
+ msgid "Via %s ending in %s"
 
1094
  msgstr ""
1095
 
1096
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:515
1097
+ msgid "Subscriptions"
 
1098
  msgstr ""
1099
 
1100
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:584
1101
+ msgid ""
1102
+ "This payment method is tied to a subscription and cannot be deleted. Please "
1103
+ "switch the subscription to another method first."
1104
  msgstr ""
1105
 
1106
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:636
1107
+ msgid "Payment Token"
1108
  msgstr ""
1109
 
1110
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:665
1111
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:670
1112
+ msgid "%s is required."
1113
  msgstr ""
1114
 
1115
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:136
1116
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2177
1117
+ #. translators: Placeholders: %1$s - payment request response status code, %2$s
1118
+ #. - payment request response status message
1119
+ #. translators: Placeholders: %1$s - status code, %2$s - status message
1120
+ msgid "Status code %1$s: %2$s"
1121
  msgstr ""
1122
 
1123
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:139
1124
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2180
1125
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:791
1126
+ #. translators: Placeholders: %s - payment request response status code
1127
+ #. translators: Placeholders: %s - status code
1128
+ msgid "Status code: %s"
1129
  msgstr ""
1130
 
1131
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:142
1132
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2183
1133
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:793
1134
+ #. translators: Placeholders: %s - payment request response status message
1135
+ #. translators: Placeholders; %s - status message
1136
+ msgid "Status message: %s"
1137
  msgstr ""
1138
 
1139
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:144
1140
+ msgid "Unknown Error"
1141
  msgstr ""
1142
 
1143
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:149
1144
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2188
1145
+ msgid "Transaction ID %s"
1146
  msgstr ""
1147
 
1148
+ #: includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php:803
1149
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1150
+ #. Authorize.net, Braintree, etc), %2$s - payment method name (mastercard, bank
1151
+ #. account, etc), %3$s - last four digits of the card/account, %4$s -
1152
+ #. card/account expiry date
1153
+ msgid "%1$s Payment Method Saved: %2$s ending in %3$s (expires %4$s)"
1154
  msgstr ""
1155
 
1156
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:305
1157
+ msgid "you successfully processed a payment!"
1158
  msgstr ""
1159
 
1160
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:310
1161
+ msgid "you successfully processed a refund!"
1162
  msgstr ""
1163
 
1164
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:437
1165
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:164
1166
+ msgid "Card number is missing"
1167
  msgstr ""
1168
 
1169
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:438
1170
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:180
1171
+ msgid "Card number is invalid"
1172
  msgstr ""
1173
 
1174
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:439
1175
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:175
1176
+ msgid "Card number is invalid (only digits allowed)"
1177
  msgstr ""
1178
 
1179
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:440
1180
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:170
1181
+ msgid "Card number is invalid (wrong length)"
1182
  msgstr ""
1183
 
1184
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:441
1185
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:219
1186
+ msgid "Card security code is missing"
1187
  msgstr ""
1188
 
1189
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:442
1190
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:207
1191
+ msgid "Card security code is invalid (only digits are allowed)"
 
 
 
 
1192
  msgstr ""
1193
 
1194
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:443
1195
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:213
1196
+ msgid "Card security code is invalid (must be 3 or 4 digits)"
1197
  msgstr ""
1198
 
1199
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:444
1200
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:140
1201
+ msgid "Card expiration date is invalid"
1202
  msgstr ""
1203
 
1204
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:445
1205
+ msgid "Check Number is invalid (only digits are allowed)"
1206
  msgstr ""
1207
 
1208
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:446
1209
+ msgid "Check Number is missing"
1210
  msgstr ""
1211
 
1212
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:447
1213
+ msgid "Drivers license state is missing"
1214
  msgstr ""
1215
 
1216
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:448
1217
+ msgid "Drivers license number is missing"
1218
  msgstr ""
1219
 
1220
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:449
1221
+ msgid "Drivers license number is invalid"
1222
  msgstr ""
1223
 
1224
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:450
1225
+ msgid "Account Number is missing"
1226
  msgstr ""
1227
 
1228
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:451
1229
+ msgid "Account Number is invalid (only digits are allowed)"
1230
  msgstr ""
1231
 
1232
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:452
1233
+ msgid "Account number is invalid (must be between 5 and 17 digits)"
1234
  msgstr ""
1235
 
1236
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:453
1237
+ msgid "Routing Number is missing"
1238
  msgstr ""
1239
 
1240
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:454
1241
+ msgid "Routing Number is invalid (only digits are allowed)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1242
  msgstr ""
1243
 
1244
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:455
1245
+ msgid "Routing number is invalid (must be 9 digits)"
1246
  msgstr ""
1247
 
1248
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:593
1249
+ msgid "Continue"
1250
  msgstr ""
1251
 
1252
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:593
1253
+ msgid "Place order"
1254
  msgstr ""
1255
 
1256
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:625
1257
+ msgid "Thank you for your order."
 
 
1258
  msgstr ""
1259
 
1260
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1034
1261
+ #: includes/Gateway/Blocks_Handler.php:152
1262
+ msgid "Credit Card"
1263
  msgstr ""
1264
 
1265
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1052
1266
+ msgid "Pay securely using your credit card."
1267
  msgstr ""
1268
 
1269
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1072
1270
+ #: includes/Gateway.php:587
1271
+ msgid "Enable this gateway"
1272
  msgstr ""
1273
 
1274
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1078
1275
+ #: includes/Gateway.php:593
1276
+ msgid "Title"
1277
  msgstr ""
1278
 
1279
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1080
1280
+ #: includes/Gateway.php:595
1281
+ msgid "Payment method title that the customer will see during checkout."
1282
  msgstr ""
1283
 
1284
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1085
1285
+ #: includes/Gateway.php:600
1286
+ msgid "Description"
1287
  msgstr ""
1288
 
1289
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1087
1290
+ #: includes/Gateway.php:602
1291
+ msgid "Payment method description that the customer will see during checkout."
1292
  msgstr ""
1293
 
1294
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1116
1295
+ #: includes/Gateway.php:636
1296
+ msgid "Detailed Decline Messages"
1297
  msgstr ""
1298
 
1299
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1118
1300
+ #: includes/Gateway.php:638
1301
+ msgid ""
1302
+ "Check to enable detailed decline messages to the customer during checkout "
1303
+ "when possible, rather than a generic decline message."
1304
  msgstr ""
1305
 
1306
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1128
1307
+ #: includes/Gateway.php:648
1308
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
1309
+ msgid ""
1310
+ "Show Detailed Error Messages and API requests/responses on the checkout "
1311
+ "page and/or save them to the %1$sdebug log%2$s"
1312
  msgstr ""
1313
 
1314
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1132
1315
+ #: includes/Gateway.php:652
1316
+ msgid "Show on Checkout Page"
1317
  msgstr ""
1318
 
1319
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1135
1320
+ #: includes/Gateway.php:655
1321
+ #. translators: show debugging information on both checkout page and in the log
1322
+ msgid "Both"
1323
  msgstr ""
1324
 
1325
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1198
1326
+ msgid "Select the gateway environment to use for transactions."
1327
  msgstr ""
1328
 
1329
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1252
1330
+ msgid "Share connection settings"
1331
  msgstr ""
1332
 
1333
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1254
1334
+ msgid "Use connection/authentication settings from other gateway"
1335
  msgstr ""
1336
 
1337
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1257
1338
+ msgid "Disabled because the other gateway is using these settings"
1339
  msgstr ""
1340
 
1341
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1274
1342
+ msgid "Card Verification (CSC)"
1343
  msgstr ""
1344
 
1345
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1275
1346
+ msgid "Display the Card Security Code (CV2) field on checkout"
 
 
1347
  msgstr ""
1348
 
1349
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1283
1350
+ msgid "Saved Card Verification"
1351
  msgstr ""
1352
 
1353
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1284
1354
+ msgid "Display the Card Security Code field when paying with a saved card"
1355
  msgstr ""
1356
 
1357
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1566
1358
+ #. translators: Placeholders: %1$s - site title, %2$s - order number
1359
+ msgid "%1$s - Order %2$s"
1360
  msgstr ""
1361
 
1362
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1691
1363
+ #. translators: Placeholders: %1$s - site title, %2$s - order number.
1364
+ #. Definitions: Capture as in capture funds from a credit card.
1365
+ msgid "%1$s - Capture for Order %2$s"
1366
  msgstr ""
1367
 
1368
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1813
1369
+ #. translators: Placeholders: %1$s - site title, %2$s - order number
1370
+ msgid "%1$s - Refund for Order %2$s"
1371
  msgstr ""
1372
 
1373
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1866
1374
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1375
+ #. Authorize.net, Braintree, etc), %2$s - a monetary amount
1376
+ msgid "%1$s Refund in the amount of %2$s approved."
1377
  msgstr ""
1378
 
1379
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1894
1380
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1381
+ #. Authorize.net, Braintree, etc), %2$s - error code, %3$s - error message
1382
+ msgid "%1$s Refund Failed: %2$s - %3$s"
1383
  msgstr ""
1384
 
1385
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1902
1386
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1387
+ #. Authorize.net, Braintree, etc), %2$s - error message
1388
+ msgid "%1$s Refund Failed: %2$s"
 
 
 
 
1389
  msgstr ""
1390
 
1391
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1923
1392
+ #. translators: Placeholders: %s - payment gateway title (such as
1393
+ #. Authorize.net, Braintree, etc)
1394
+ msgid "%s Order completely refunded."
1395
  msgstr ""
1396
 
1397
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:1978
1398
+ msgid ""
1399
+ "Oops, you cannot partially void this order. Please use the full order "
1400
+ "amount."
1401
  msgstr ""
1402
 
1403
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2048
1404
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - error code,
1405
+ #. %3$s - error message. Void as in to void an order.
1406
+ msgid "%1$s Void Failed: %2$s - %3$s"
1407
  msgstr ""
1408
 
1409
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2056
1410
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
1411
+ #. message. Void as in to void an order.
1412
+ msgid "%1$s Void Failed: %2$s"
 
 
 
 
1413
  msgstr ""
1414
 
1415
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2080
1416
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - a monetary
1417
+ #. amount. Void as in to void an order.
1418
+ msgid "%1$s Void in the amount of %2$s approved."
 
 
 
 
 
 
 
 
 
 
 
 
 
1419
  msgstr ""
1420
 
1421
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2358
1422
+ #. translators: Placeholders: %1$s - payment method title, %2$s - environment
1423
+ #. ("Test"), %3$s - transaction type (authorization/charge)
1424
+ msgid "%1$s %2$s %3$s Approved"
1425
+ msgstr ""
 
1426
 
1427
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2368
1428
+ #. translators: Placeholders: %1$s - credit card type (MasterCard, Visa,
1429
+ #. etc...), %2$s - last four digits of the card
1430
+ msgid "%1$s ending in %2$s"
1431
  msgstr ""
1432
 
1433
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2379
1434
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:576
1435
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:528
1436
+ #. translators: Placeholders: %s - expiry date
1437
+ msgid "(expires %s)"
1438
  msgstr ""
1439
 
1440
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2418
1441
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - message
1442
+ #. (probably reason for the transaction being held for review)
1443
+ msgid "%1$s Transaction Held for Review (%2$s)"
 
1444
  msgstr ""
1445
 
1446
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2459
1447
+ msgid ""
1448
+ "Your order has been received and is being reviewed. Thank you for your "
1449
+ "business."
1450
  msgstr ""
1451
 
1452
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2506
1453
+ #. translators: Placeholders: %1$s - payment gateway title, %2$s - error
1454
+ #. message; e.g. Order Note: [Payment method] Payment failed [error]
1455
+ msgid "%1$s Payment Failed (%2$s)"
1456
  msgstr ""
1457
 
1458
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2755
1459
+ msgid "Transaction Type"
1460
  msgstr ""
1461
 
1462
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2757
1463
+ msgid ""
1464
+ "Select how transactions should be processed. Charge submits all "
1465
+ "transactions for settlement, Authorization simply authorizes the order "
1466
+ "total for capture later."
1467
  msgstr ""
1468
 
1469
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2768
1470
+ msgid "Charge Virtual-Only Orders"
1471
  msgstr ""
1472
 
1473
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2770
1474
+ msgid ""
1475
+ "If the order contains exclusively virtual items, enable this to immediately "
1476
+ "charge, rather than authorize, the transaction."
1477
  msgstr ""
1478
 
1479
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2778
1480
+ msgid "Enable Partial Capture"
1481
+ msgstr ""
 
 
1482
 
1483
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2780
1484
+ msgid "Allow orders to be partially captured multiple times."
1485
+ msgstr ""
 
 
1486
 
1487
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2792
1488
+ msgid "Capture Paid Orders"
1489
  msgstr ""
1490
 
1491
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2795
1492
+ msgid "Automatically capture orders when they are changed to %s."
1493
  msgstr ""
1494
 
1495
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2796
1496
+ msgid "a paid status"
1497
  msgstr ""
1498
 
1499
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2986
1500
+ msgid "Accepted Card Logos"
1501
  msgstr ""
1502
 
1503
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2988
1504
+ msgid ""
1505
+ "These are the card logos that are displayed to customers as accepted during "
1506
+ "checkout."
1507
  msgstr ""
1508
 
1509
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2991
1510
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag
1511
+ msgid ""
1512
+ "This setting %1$sdoes not%2$s change which card types the gateway will "
1513
+ "accept. Accepted cards are configured from your payment processor account."
1514
  msgstr ""
1515
 
1516
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3082
1517
+ #. translators:
1518
+ #. http:www.cybersource.com/products/payment_security/payment_tokenization/ and
1519
+ #. https:en.wikipedia.org/wiki/Tokenization_(data_security)
1520
+ msgid "Tokenization"
1521
  msgstr ""
1522
 
1523
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3083
1524
+ msgid "Allow customers to securely save their payment details for future checkout."
 
1525
  msgstr ""
1526
 
1527
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:42
1528
+ msgid ""
1529
+ "Payment error, please try another payment method or contact us to complete "
1530
+ "your transaction."
1531
  msgstr ""
1532
 
1533
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:387
1534
+ msgid "Unknown error"
1535
  msgstr ""
1536
 
1537
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:396
1538
+ msgid "Payment method address could not be updated. %s"
1539
  msgstr ""
1540
 
1541
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:563
1542
+ #. translators: Placeholders: %1$s - payment method title, %2$s - environment
1543
+ #. ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type
1544
+ #. (mastercard, visa, ...), %5$s - last four digits of the card
1545
+ msgid "%1$s %2$s %3$s Approved: %4$s ending in %5$s"
1546
  msgstr ""
1547
 
1548
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:646
1549
+ #. translators: Placeholders: %s - failure message
1550
+ msgid "Tokenization Request Failed: %s"
1551
  msgstr ""
1552
 
1553
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:657
1554
+ #. translators: Placeholders: %1$s - payment method title, %2$s - failure
1555
+ #. message
1556
+ msgid "%1$s Tokenization Request Failed: %2$s"
1557
  msgstr ""
1558
 
1559
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:715
1560
+ #. translators: Placeholders: %s - failure message. Payment method as in a
1561
+ #. specific credit card, e-check or bank account
1562
+ msgid "Oops, adding your new payment method failed: %s"
1563
  msgstr ""
1564
 
1565
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:756
1566
+ #. translators: Payment method as in a specific credit card. Placeholders: %1$s
1567
+ #. - card type (visa, mastercard, ...), %2$s - last four digits of the card,
1568
+ #. %3$s - card expiry date
1569
+ msgid "Nice! New payment method added: %1$s ending in %2$s (expires %3$s)"
1570
+ msgstr ""
1571
+
1572
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:764
1573
+ #. translators: Payment method as in a specific credit card, e-check or bank
1574
+ #. account
1575
+ msgid "Nice! New payment method added."
1576
  msgstr ""
1577
 
1578
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:789
1579
+ msgid "Status code %s: %s"
1580
  msgstr ""
1581
 
1582
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:884
1583
+ #. translators: Placeholders: %1$s - site title, %2$s - customer email. Payment
1584
+ #. method as in a specific credit card, e-check or bank account
1585
+ msgid "%1$s - Add Payment Method for %2$s"
1586
  msgstr ""
1587
 
1588
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:152
1589
+ msgid "PayPal"
1590
  msgstr ""
1591
 
1592
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:153
1593
+ msgid "Checking Account"
1594
  msgstr ""
1595
 
1596
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:154
1597
+ msgid "Savings Account"
 
1598
  msgstr ""
1599
 
1600
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:155
1601
+ msgid "Credit / Debit Card"
1602
+ msgstr ""
1603
+
1604
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:156
1605
+ msgid "Bank Account"
1606
+ msgstr ""
1607
+
1608
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:202
1609
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:631
1610
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:35
1611
+ msgid "Edit"
1612
  msgstr ""
1613
 
1614
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:204
1615
+ msgid "Oops, there was an error updating your payment method. Please try again."
1616
  msgstr ""
1617
 
1618
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:205
1619
+ msgid "Are you sure you want to delete this payment method?"
1620
  msgstr ""
1621
 
1622
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:311
1623
+ msgid "Method"
1624
  msgstr ""
1625
 
1626
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:312
1627
+ msgid "Details"
 
1628
  msgstr ""
1629
 
1630
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:313
1631
+ msgid "Expires"
1632
  msgstr ""
1633
 
1634
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:314
1635
+ msgid "Default?"
1636
  msgstr ""
1637
 
1638
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:351
1639
+ msgid "Credit/Debit Cards"
1640
  msgstr ""
1641
 
1642
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:360
1643
+ msgid "Bank Accounts"
1644
  msgstr ""
1645
 
1646
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:415
1647
+ msgid "N/A"
1648
+ msgstr ""
1649
+
1650
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:511
1651
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:174
1652
+ msgid "Nickname"
1653
+ msgstr ""
1654
+
1655
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:692
1656
+ #: includes/Sync/Records/Record.php:544
1657
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:92
1658
+ msgid "Delete"
1659
+ msgstr ""
1660
+
1661
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:846
1662
+ msgid "Oops, you took too long, please try again."
1663
+ msgstr ""
1664
+
1665
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:859
1666
+ msgid "There was an error with your request, please try again."
1667
+ msgstr ""
1668
+
1669
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:872
1670
+ #. translators: Payment method as in a specific credit card, e-check or bank
1671
+ #. account
1672
+ msgid "Error removing payment method"
1673
+ msgstr ""
1674
+
1675
+ #: includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php:877
1676
+ #. translators: Payment method as in a specific credit card, e-check or bank
1677
+ #. account
1678
+ msgid "Payment method deleted."
1679
+ msgstr ""
1680
+
1681
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:268
1682
+ msgid "Card Number"
1683
+ msgstr ""
1684
+
1685
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:289
1686
+ msgid "MM / YY"
1687
+ msgstr ""
1688
+
1689
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:307
1690
+ msgid "Card Security Code"
1691
+ msgstr ""
1692
+
1693
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:310
1694
+ msgid "CSC"
1695
+ msgstr ""
1696
+
1697
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:355
1698
+ #. translators: Test mode refers to the current software environment
1699
+ msgid "TEST MODE ENABLED"
1700
+ msgstr ""
1701
+
1702
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:430
1703
+ #. translators: Payment method as in a specific credit card, eCheck or bank
1704
+ #. account
1705
+ msgid "Manage Payment Methods"
1706
+ msgstr ""
1707
+
1708
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:567
1709
+ msgid "Use a new card"
1710
  msgstr ""
1711
 
1712
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:567
1713
+ msgid "Use a new bank account"
1714
  msgstr ""
1715
 
1716
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Payment_Form.php:630
1717
+ #. translators: account as in customer's account on the eCommerce site
1718
+ msgid "Securely Save to Account"
1719
  msgstr ""
1720
 
1721
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:550
1722
+ #. translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a>
1723
+ #. tag
1724
+ msgid ""
1725
+ "%1$s: WooCommerce is not being forced over SSL; your customers' payment "
1726
+ "data may be at risk. %2$sVerify your site URLs here%3$s"
1727
  msgstr ""
1728
 
1729
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:567
1730
+ #. translators: Placeholders: %s - payment gateway name
1731
  msgid ""
1732
+ "%s will soon require TLS 1.2 support to process transactions and your "
1733
+ "server environment may need to be updated. Please contact your hosting "
1734
+ "provider to confirm that your site can send and receive TLS 1.2 connections "
1735
+ "and request they make any necessary updates."
1736
+ msgstr ""
 
 
1737
 
1738
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:623
1739
+ #. translators: Placeholders: %1$s - plugin name, %2$s - a
1740
+ #. currency/comma-separated list of currencies, %3$s - <a> tag, %4$s - </a> tag
1741
  msgid ""
1742
+ "%1$s accepts payment in %2$s only. %3$sConfigure%4$s WooCommerce to accept "
1743
+ "%2$s to enable this gateway for checkout."
1744
  msgid_plural ""
1745
+ "%1$s accepts payment in one of %2$s only. %3$sConfigure%4$s WooCommerce to "
1746
+ "accept one of %2$s to enable this gateway for checkout."
1747
  msgstr[0] ""
1748
  msgstr[1] ""
1749
 
1750
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:658
1751
+ #. translators: Placeholders: %1$s - payment gateway name, %2$s - opening <a>
1752
+ #. tag, %3$s - closing </a> tag
1753
+ msgid ""
1754
+ "Heads up! %1$s is currently configured to log transaction data for "
1755
+ "debugging purposes. If you are not experiencing any problems with payment "
1756
+ "processing, we recommend %2$sturning off Debug Mode%3$s"
1757
+ msgstr ""
1758
+
1759
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:697
1760
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1761
+ #. Authorize.net, Braintree, etc), %2$s - <a> tag, %3$s - </a> tag
1762
+ msgid ""
1763
+ "%1$s is inactive for subscription transactions. Please %2$senable "
1764
+ "tokenization%3$s to activate %1$s for Subscriptions."
1765
+ msgstr ""
1766
+
1767
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:715
1768
+ #. translators: Placeholders: %1$s - payment gateway title (such as
1769
+ #. Authorize.net, Braintree, etc), %2$s - <a> tag, %3$s - </a> tag
1770
  msgid ""
1771
+ "%1$s is inactive for pre-order transactions. Please %2$senable "
1772
+ "tokenization%3$s to activate %1$s for Pre-Orders."
1773
  msgstr ""
1774
 
1775
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:752
1776
  msgid ""
1777
+ "You must enable tokenization for this gateway in order to support automatic "
1778
+ "renewal payments with the WooCommerce Subscriptions extension."
1779
  msgstr ""
1780
 
1781
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Plugin.php:753
1782
+ msgid "Inactive"
 
 
1783
  msgstr ""
1784
 
1785
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:89
1786
+ msgid "%s Customer ID"
1787
+ msgstr ""
1788
+
1789
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:158
1790
+ msgid "Type"
1791
+ msgstr ""
1792
+
1793
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:228
1794
+ msgid "Removed payment token \"%d\""
1795
+ msgstr ""
1796
+
1797
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:273
1798
+ msgid "Account Type"
1799
+ msgstr ""
1800
+
1801
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Privacy.php:275
1802
+ msgid "Expiry Date"
1803
+ msgstr ""
1804
+
1805
+ #: includes/Framework/Plugin.php:208
1806
+ #. translators: Placeholders: %s - plugin name
1807
+ msgid "You cannot clone instances of %s."
1808
+ msgstr ""
1809
+
1810
+ #: includes/Framework/Plugin.php:219
1811
+ #. translators: Placeholders: %s - plugin name
1812
+ msgid "You cannot unserialize instances of %s."
1813
+ msgstr ""
1814
+
1815
+ #: includes/Framework/Plugin.php:348
1816
+ #. translators: Docs as in Documentation
1817
+ msgid "Docs"
1818
+ msgstr ""
1819
+
1820
+ #: includes/Framework/Plugin.php:437
1821
+ msgid "%1$s - A minimum of %2$s is required."
1822
+ msgstr ""
1823
+
1824
+ #: includes/Framework/Plugin.php:446
1825
+ msgid "Set as %1$s - %2$s is required."
1826
+ msgstr ""
1827
+
1828
+ #: includes/Framework/Plugin.php:631
1829
+ msgid "Configure"
1830
+ msgstr ""
1831
+
1832
+ #. Author of the plugin/theme
1833
+ msgid "WooCommerce"
1834
  msgstr ""
1835
 
1836
+ #: includes/Framework/Plugin_Dependencies.php:125
1837
  #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP
1838
  #. extension/comma-separated list of PHP extensions
1839
  msgid ""
1846
  msgstr[0] ""
1847
  msgstr[1] ""
1848
 
1849
+ #: includes/Framework/Plugin_Dependencies.php:153
1850
  #. translators: Placeholders: %1$s - plugin name, %2$s - a PHP
1851
  #. function/comma-separated list of PHP functions
1852
  msgid ""
1858
  msgstr[0] ""
1859
  msgstr[1] ""
1860
 
1861
+ #: includes/Framework/Plugin_Dependencies.php:183
1862
  #. translators: Placeholders: %s - plugin name
1863
  msgid ""
1864
  "%s may behave unexpectedly because the following PHP configuration settings "
1865
  "are required:"
1866
  msgstr ""
1867
 
1868
+ #: includes/Framework/Plugin_Dependencies.php:197
1869
+ #. translators: Placeholders: %s - a PHP setting value
1870
  msgid "%s or higher"
1871
  msgstr ""
1872
 
1873
+ #: includes/Framework/Plugin_Dependencies.php:207
1874
  msgid ""
1875
  "Please contact your hosting provider or server administrator to configure "
1876
  "these settings."
1877
  msgstr ""
1878
 
1879
+ #: includes/Framework/Plugin_Dependencies.php:229
1880
  #. translators: Placeholders: %1$s - <strong>, %2$s - </strong>
1881
  msgid ""
1882
  "Hey there! We've noticed that your server is running %1$san outdated "
1891
  "resources to help you upgrade%5$s and to explain PHP versions further."
1892
  msgstr ""
1893
 
1894
+ #: includes/Framework/Plugin_Dependencies.php:253
1895
  #. translators: Placeholders: %1$s - WooCommerce version number, %2$s -
1896
  #. <strong>, %3$s - </strong>, %4$s - Plugin name, %5$s - <a> tag, %6$s - </a>
1897
  #. tag
1902
  "soon as possible."
1903
  msgstr ""
1904
 
1905
+ #: includes/Framework/Utilities/WP_Background_Job_Handler.php:619
1906
+ msgid "Every %d Minutes"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1907
  msgstr ""
1908
 
1909
+ #: includes/Gateway/API/Requests/Orders.php:279
1910
+ #: includes/Gateway/API/Requests/Orders.php:318
1911
+ msgid "Adjustment"
1912
  msgstr ""
1913
 
1914
+ #: includes/Gateway/Blocks_Handler.php:298
1915
+ #. translators: %1$s - opening bold HTML tag, %2$s - closing bold HTML tag,
1916
+ #. %3$s - version number
1917
+ msgid ""
1918
+ "%1$sWarning!%2$s Some Square + Checkout Block features do not work with "
1919
+ "your version of WooCommerce Blocks (%3$s). Please update to the latest "
1920
+ "version of WooCommerce Blocks or WooCommerce to fix these issues."
1921
  msgstr ""
1922
 
1923
+ #: includes/Gateway/Digital_Wallet.php:114
1924
+ #. Translators: %1$s: expected location of apple pay verification file, %2$s:
1925
+ #. opening href tag with link to Square documentation, %3$s: closing href tag
1926
  msgid ""
1927
+ "Apple Pay is not available with Square. We cannot confirm the Apple Pay "
1928
+ "domain verification file is at the expected location: %1$s. For more "
1929
+ "information, please read our documentation on %2$sSetting up Apple Pay%3$s."
1930
  msgstr ""
1931
 
1932
+ #: includes/Gateway/Digital_Wallet.php:130
1933
+ #. Translators: %1$s: opening bold tags, %2$s: closing strong/bold tags, %3$s:
1934
+ #. expected location of apple pay verification file, %4$s: opening href tag
1935
+ #. with link to Square documentation, %5$s: closing href tag
1936
+ msgid ""
1937
+ "Apple Pay is not available with Square - there was a problem with "
1938
+ "registering your store domain with Square/Apple Pay. %1$sView the Square "
1939
+ "logs%2$s to find out what caused the registration to fail."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1940
  msgstr ""
1941
 
1942
+ #: includes/Gateway/Digital_Wallet.php:177
1943
+ msgid "OR"
 
 
 
1944
  msgstr ""
1945
 
1946
+ #: includes/Gateway/Digital_Wallet.php:279
1947
+ #. translators: product ID
1948
+ msgid "Product with the ID (%d) cannot be found."
1949
  msgstr ""
1950
 
1951
+ #: includes/Gateway/Digital_Wallet.php:295
1952
+ #. translators: 1: product name 2: quantity in stock
1953
  msgid ""
1954
+ "You cannot add that amount of \"%1$s\"; to the cart because there is not "
1955
+ "enough stock (%2$s remaining)."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1956
  msgstr ""
1957
 
1958
+ #: includes/Gateway/Digital_Wallet.php:300
1959
+ #. translators: 1: product name
1960
+ msgid "You cannot purchase \"%1$s\" because it is currently not available."
1961
  msgstr ""
1962
 
1963
+ #: includes/Gateway/Digital_Wallet.php:322
1964
+ #: includes/Gateway/Digital_Wallet.php:418
1965
+ msgid "Tax"
1966
  msgstr ""
1967
 
1968
+ #: includes/Gateway/Digital_Wallet.php:357
1969
+ msgid "This payment method cannot be used for multiple shipments."
1970
  msgstr ""
1971
 
1972
+ #: includes/Gateway/Digital_Wallet.php:368
1973
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:378
1974
+ msgid "Pending"
1975
  msgstr ""
1976
 
1977
+ #: includes/Gateway/Digital_Wallet.php:469
1978
+ #. translators: Context (product, cart, checkout or page)
1979
+ msgid "Empty payment request data for %s."
1980
  msgstr ""
1981
 
1982
+ #: includes/Gateway/Digital_Wallet.php:663
1983
+ msgid "Empty cart"
1984
  msgstr ""
1985
 
1986
+ #: includes/Gateway/Digital_Wallet.php:797
1987
+ msgid "Unable to verify domain with Apple Pay - missing access token."
 
 
 
1988
  msgstr ""
1989
 
1990
+ #: includes/Gateway/Payment_Form.php:180
1991
+ msgid "Postal code"
 
 
 
 
 
 
 
 
1992
  msgstr ""
1993
 
1994
+ #: includes/Gateway.php:83
1995
+ msgid "Allow customers to use Square to securely pay with their credit cards"
 
 
 
1996
  msgstr ""
1997
 
1998
+ #: includes/Gateway.php:449
1999
+ msgid "Refunds must be made within %s of the original payment date."
2000
  msgstr ""
2001
 
2002
+ #: includes/Gateway.php:473
2003
  msgid ""
2004
+ "Could not find original transaction tender. Please refund this transaction "
2005
+ "from your Square dashboard."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2006
  msgstr ""
2007
 
2008
+ #: includes/Gateway.php:629
2009
+ msgid "Advanced Settings"
2010
  msgstr ""
2011
 
2012
+ #: includes/Gateway.php:691
2013
+ msgid "Customer Profiles"
2014
  msgstr ""
2015
 
2016
+ #: includes/Gateway.php:692
2017
+ msgid ""
2018
+ "Check to enable tokenization and allow customers to securely save their "
2019
+ "payment details for future checkout."
2020
  msgstr ""
2021
 
2022
+ #: includes/Gateway.php:750
2023
+ msgid "Digital Wallet Settings"
2024
  msgstr ""
2025
 
2026
+ #: includes/Gateway.php:751
2027
+ msgid "Take payments on your store with Apple Pay and Google Pay."
 
2028
  msgstr ""
2029
 
2030
+ #: includes/Gateway.php:758
2031
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
2032
+ msgid ""
2033
+ "Allow customers to pay with Apple Pay or Google Pay from your Product, Cart "
2034
+ "and Checkout pages. Read more about the availablity of digital wallets in "
2035
+ "our %1$sdocumentation%2$s."
2036
  msgstr ""
2037
 
2038
+ #: includes/Gateway.php:761
2039
+ msgid "Enable digital wallets"
 
2040
  msgstr ""
2041
 
2042
+ #: includes/Gateway.php:765
2043
+ msgid "Button Type"
 
2044
  msgstr ""
2045
 
2046
+ #: includes/Gateway.php:766
2047
+ msgid ""
2048
+ "This setting only applies to the Apple Pay button. When Google Pay is "
2049
+ "available, the Google Pay button will always have the \"Buy with\" button "
2050
+ "text."
2051
  msgstr ""
2052
 
2053
+ #: includes/Gateway.php:767
2054
+ msgid "Select which text is displayed on the digital wallet buttons."
 
2055
  msgstr ""
2056
 
2057
+ #: includes/Gateway.php:779
2058
+ msgid "Apple Pay Button Color"
 
 
 
2059
  msgstr ""
2060
 
2061
+ #: includes/Gateway.php:780
2062
+ msgid "Select the color of the Apple Pay button."
2063
  msgstr ""
2064
 
2065
+ #: includes/Gateway.php:792
2066
+ msgid "Google Pay Button Color"
2067
  msgstr ""
2068
 
2069
+ #: includes/Gateway.php:793
2070
+ msgid "Select the color of the Google Pay button."
2071
  msgstr ""
2072
 
2073
+ #: includes/Gateway.php:804
2074
+ msgid "Hide Digital Wallet Buttons"
2075
  msgstr ""
2076
 
2077
+ #: includes/Gateway.php:805
2078
+ msgid ""
2079
+ "Select any digital wallet buttons you don't want to be displayed on your "
2080
+ "store."
2081
  msgstr ""
2082
 
2083
+ #: includes/Gateway.php:1089
2084
+ msgid " An error occurred, please try again or try an alternate form of payment."
2085
  msgstr ""
2086
 
2087
+ #: includes/Handlers/Background_Job.php:236
2088
+ msgid "Clear Square Sync"
 
2089
  msgstr ""
2090
 
2091
+ #: includes/Handlers/Background_Job.php:237
2092
+ msgid "Clear"
 
2093
  msgstr ""
2094
 
2095
+ #: includes/Handlers/Background_Job.php:238
2096
+ msgid "This tool will clear any ongoing Square product syncs."
2097
  msgstr ""
2098
 
2099
+ #: includes/Handlers/Background_Job.php:288
2100
+ msgid "Success! You can now sync your products."
 
 
2101
  msgstr ""
2102
 
2103
+ #: includes/Handlers/Connection.php:101 includes/Handlers/Connection.php:169
2104
+ msgid "Sorry, you do not have permission to manage the Square connection."
2105
  msgstr ""
2106
 
2107
+ #: includes/Handlers/Connection.php:113
2108
+ msgid "Square Error: We could not connect to Square. No access token was given.!"
2109
  msgstr ""
2110
 
2111
+ #: includes/Handlers/Connection.php:177
2112
+ msgid "Disconnected successfully"
2113
  msgstr ""
2114
 
2115
+ #: includes/Handlers/Connection.php:384
2116
+ msgid "Connect with Square"
2117
  msgstr ""
2118
 
2119
+ #: includes/Handlers/Connection.php:404
2120
+ msgid "Disconnect from Square"
2121
  msgstr ""
2122
 
2123
+ #: includes/Handlers/Product.php:175
2124
+ #. translators: Placeholder: %s category ID
2125
+ msgid ""
2126
+ "Square category with id (%s) was not imported to your Store. Please run "
2127
+ "Import Products from Square settings."
2128
  msgstr ""
2129
 
2130
+ #: includes/Handlers/Product.php:309
2131
+ msgid "Product not synced with Square"
2132
  msgstr ""
2133
 
2134
+ #: includes/Handlers/Products.php:66
2135
+ #. translators: Placeholder: %s - product name
2136
+ msgid ""
2137
+ "Please add an SKU to sync %s with Square. The SKU must match the item's SKU "
2138
+ "in your Square account."
2139
  msgstr ""
2140
 
2141
+ #: includes/Handlers/Products.php:68
2142
+ #. translators: Placeholder: %s - product name
2143
+ msgid ""
2144
+ "Please add an SKU to every variation of %s for syncing with Square. Each "
2145
+ "SKU must be unique and match the corresponding item's SKU in your Square "
2146
+ "account."
2147
  msgstr ""
2148
 
2149
+ #: includes/Handlers/Products.php:70
2150
+ #. translators: Placeholder: %s - product name
2151
+ msgid "%s has multiple variation attributes and cannot be synced with Square."
2152
  msgstr ""
2153
 
2154
+ #: includes/Handlers/Products.php:250
2155
+ msgid "Update product data with Square data"
2156
  msgstr ""
2157
 
2158
+ #: includes/Handlers/Products.php:250
2159
+ msgid "Send product data to Square"
2160
  msgstr ""
2161
 
2162
+ #: includes/Handlers/Products.php:255
2163
+ msgid "Sync with Square"
2164
  msgstr ""
2165
 
2166
+ #: includes/Handlers/Products.php:291
2167
+ msgid "Sync with Square?"
2168
  msgstr ""
2169
 
2170
+ #: includes/Handlers/Products.php:295
2171
+ msgid "No change"
2172
  msgstr ""
2173
 
2174
+ #: includes/Handlers/Products.php:297
2175
+ msgid "No"
 
2176
  msgstr ""
2177
 
2178
+ #: includes/Handlers/Products.php:298
2179
+ msgid "Yes"
 
 
 
2180
  msgstr ""
2181
 
2182
+ #: includes/Handlers/Products.php:304
2183
+ msgid "This product"
 
 
2184
  msgstr ""
2185
 
2186
+ #: includes/Handlers/Products.php:675
2187
+ #. translators: Placeholder: %1$s - date (localized), %2$s - time (localized),
2188
+ #. %3$s - opening <a> HTML link tag, %4$s closing </a> HTML link tag
2189
  msgid ""
2190
+ "The product catalog visibility has been set to \"hidden\", as a matching "
2191
+ "product could not be found in Square on %1$s at %2$s. %3$sCheck sync "
2192
+ "records%4$s."
2193
  msgstr ""
2194
 
2195
+ #: includes/Handlers/Sync.php:291
2196
+ #. translators: Placeholder: %d number of products processed
2197
+ msgid "Updated data for %d product."
2198
+ msgid_plural "Updated data for %d products."
2199
+ msgstr[0] ""
2200
+ msgstr[1] ""
2201
 
2202
+ #: includes/Lifecycle.php:185
2203
+ msgid "Great"
2204
  msgstr ""
2205
 
2206
+ #: includes/Plugin.php:288
2207
  msgid ""
2208
+ "Heads up! There may be a problem with your connection to Square. In order "
2209
+ "to continue accepting payments, please %1$sdisconnect and re-connect your "
2210
+ "site%2$s."
2211
  msgstr ""
2212
 
2213
+ #: includes/Plugin.php:305
2214
+ msgid "You are connected to Square!"
 
 
 
2215
  msgstr ""
2216
 
2217
+ #: includes/Plugin.php:312
2218
+ msgid "To get started, set your business location."
2219
  msgstr ""
2220
 
2221
+ #: includes/Plugin.php:318
2222
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
2223
+ msgid "Visit the %1$splugin settings%2$s to set your business location."
2224
  msgstr ""
2225
 
2226
+ #: includes/Plugin.php:328
2227
+ msgid "You are ready to sync products!"
2228
  msgstr ""
2229
 
2230
+ #: includes/Plugin.php:334
2231
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - product count, %3$s -
2232
+ #. </strong> tag, %4$s - <a> tag, %5$s - </a> tag
2233
+ msgid ""
2234
+ "%1$s%2$d products%3$s are marked \"sync with Square\". %4$sStart a new sync "
2235
+ "now &raquo;%5$s"
2236
  msgstr ""
2237
 
2238
+ #: includes/Plugin.php:346
2239
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
2240
+ #. <a> tag, %4$s - </a> tag
2241
+ msgid ""
2242
+ "%1$sNo products%2$s are marked \"sync with Square\". %3$sUpdate your "
2243
+ "products to sync data &raquo;%4$s"
2244
  msgstr ""
2245
 
2246
+ #: includes/Plugin.php:361
2247
+ msgid ""
2248
+ "Heads up! Square is configured to sync product inventory, but WooCommerce "
2249
+ "stock management is disabled. Please %1$senable stock management%2$s to "
2250
+ "ensure product inventory counts are kept in sync."
2251
  msgstr ""
2252
 
2253
+ #: includes/Plugin.php:378
2254
+ msgid "To get started, connect with Square."
2255
  msgstr ""
2256
 
2257
+ #: includes/Plugin.php:384
2258
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
2259
+ msgid "To get started, %1$sconnect with Square &raquo;%2$s"
2260
  msgstr ""
2261
 
2262
+ #: includes/Plugin.php:392
2263
+ #. translators: Placeholders: %1$s - plugin name
2264
+ msgid "Thanks for installing %1$s!"
2265
  msgstr ""
2266
 
2267
+ #: includes/Plugin.php:413
2268
+ #. translators: Placeholders: %1$s - plugin name, %2$ - plugin version number,
2269
+ #. %3$s - opening <a> HTML link tag, %4$s - closing </a> HTML link tag, %5$s -
2270
+ #. opening <a> HTML link tag, %6$s - closing </a> HTML link tag
2271
  msgid ""
2272
+ "%1$s has been updated to version %2$s. In order to continue syncing product "
2273
+ "inventory, please make sure to disconnect and reconnect with Square from "
2274
+ "the %3$splugin settings%4$s and re-sync your products. Read more in the "
2275
+ "%5$supdated documentation%6$s."
2276
  msgstr ""
2277
 
2278
+ #: includes/Plugin.php:453
2279
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
2280
+ #. 2-character country code, %4$s - comma separated list of 2-character country
2281
+ #. codes
2282
  msgid ""
2283
+ "%1$sWooCommerce Square:%2$s Your base country is %3$s, but Square can’t "
2284
+ "accept transactions from merchants outside of %4$s."
2285
  msgstr ""
2286
 
2287
+ #: includes/Plugin.php:496
2288
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
2289
+ #. <a> tag, %4$s - </a> tag
2290
  msgid ""
2291
+ "%1$sWooCommerce Square:%2$s Automatic refreshing of the connection to "
2292
+ "Square is inactive. Please disconnect and reconnect to resolve."
2293
  msgstr ""
2294
 
2295
+ #: includes/Plugin.php:528
2296
  msgid ""
2297
+ "%1$sWooCommerce Square:%2$s Product prices are entered inclusive of tax, "
2298
+ "but Square does not support syncing tax-inclusive prices. Please make sure "
2299
+ "your Square tax rates match your WooCommerce tax rates."
2300
  msgstr ""
2301
 
2302
+ #: includes/Plugin.php:559
2303
  msgid ""
2304
+ "Heads up! Your store currency is %1$s but your configured Square business "
2305
+ "location currency is %2$s, so payments cannot be processed. Please "
2306
+ "%3$schoose a different business location%4$s or change your %5$sshop "
2307
+ "currency%6$s."
2308
  msgstr ""
2309
 
2310
+ #. Plugin Name of the plugin/theme
2311
+ msgid "WooCommerce Square"
2312
  msgstr ""
2313
 
2314
+ #: includes/Settings.php:140
2315
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
2316
  msgid ""
2317
+ "Sync your products and inventory and also accept credit and debit card "
2318
+ "payments at checkout. %1$sClick here%2$s to configure payments."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2319
  msgstr ""
2320
 
2321
+ #: includes/Settings.php:147
2322
+ msgid ""
2323
+ "Connect with Square to start syncing your products and inventory and also "
2324
+ "accept credit and debit card payments at checkout."
2325
  msgstr ""
2326
 
2327
+ #: includes/Settings.php:158
2328
+ msgid "Enable Sandbox Mode"
2329
  msgstr ""
2330
 
2331
+ #: includes/Settings.php:159
2332
+ msgid "Enable to set the plugin in sandbox mode."
2333
  msgstr ""
2334
 
2335
+ #: includes/Settings.php:161
2336
+ msgid ""
2337
+ "After enabling you’ll see a new Sandbox settings section with two fields; "
2338
+ "Sandbox Application ID & Sandbox Access Token."
2339
  msgstr ""
2340
 
2341
+ #: includes/Settings.php:166
2342
+ msgid "Sandbox settings"
 
2343
  msgstr ""
2344
 
2345
+ #: includes/Settings.php:170
2346
+ #. translators: Placeholders: %1$s - URL.
2347
+ msgid "Sandbox details can be created at: %s"
2348
  msgstr ""
2349
 
2350
+ #: includes/Settings.php:177
2351
+ msgid "Sandbox Application ID"
2352
  msgstr ""
2353
 
2354
+ #: includes/Settings.php:179
2355
  msgid ""
2356
+ "Application ID for the Sandbox Application, see the details in the My "
2357
+ "Applications section."
2358
  msgstr ""
2359
 
2360
+ #: includes/Settings.php:184
2361
+ msgid "Sandbox Access Token"
2362
  msgstr ""
2363
 
2364
+ #: includes/Settings.php:186
 
 
 
 
 
 
 
 
 
 
 
 
2365
  msgid ""
2366
+ "Access Token for the Sandbox Test Account, see the details in the Sandbox "
2367
+ "Test Account section. Make sure you use the correct Sandbox Access Token "
2368
+ "for your application. For a given Sandbox Test Account, each Authorized "
2369
+ "Application is assigned a different Access Token."
 
 
 
 
 
 
 
 
 
 
2370
  msgstr ""
2371
 
2372
+ #: includes/Settings.php:193
2373
+ msgid "Business location"
2374
  msgstr ""
2375
 
2376
+ #: includes/Settings.php:198
2377
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
2378
+ #. <a> tag, %4$s - </a> tag
2379
+ msgid ""
2380
+ "Select a location to link to this site. Only %1$sactive%2$s "
2381
+ "%3$slocations%4$s that support credit card processing in Square can be "
2382
+ "linked."
2383
  msgstr ""
2384
 
2385
+ #: includes/Settings.php:208
2386
+ msgid "Product system of record"
2387
  msgstr ""
2388
 
2389
+ #: includes/Settings.php:213
2390
+ #. translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag, %3$s -
2391
+ #. <a> tag, %4$s - </a> tag
2392
+ msgid ""
2393
+ "Choose where you will update data for synced products. Inventory in Square "
2394
+ "is %1$salways%2$s checked for adjustments when sync is enabled. %3$sClick "
2395
+ "here%4$s to read more about choosing a system of record."
2396
  msgstr ""
2397
 
2398
+ #: includes/Settings.php:220
2399
+ msgid "Do not sync product data"
 
 
 
 
 
 
 
2400
  msgstr ""
2401
 
2402
+ #: includes/Settings.php:228
2403
+ msgid "Sync inventory"
2404
  msgstr ""
2405
 
2406
+ #: includes/Settings.php:229
2407
+ msgid "Enable to sync product inventory with Square"
2408
  msgstr ""
2409
 
2410
+ #: includes/Settings.php:235
2411
+ msgid "Handle missing products"
2412
  msgstr ""
2413
 
2414
+ #: includes/Settings.php:236
2415
+ msgid "Hide synced products when not found in Square"
2416
  msgstr ""
2417
 
2418
+ #: includes/Settings.php:238
2419
  msgid ""
2420
+ "Products not found in Square will be hidden in the WooCommerce product "
2421
+ "catalog."
 
 
 
 
 
2422
  msgstr ""
2423
 
2424
+ #: includes/Settings.php:244
2425
+ msgid ""
2426
+ "Run an import to create new products in this WooCommerce store for each new "
2427
+ "product created in Square that has a unique SKU not existing in here. Needs "
2428
+ "to be run each time new items are created in Square."
2429
  msgstr ""
2430
 
2431
+ #: includes/Settings.php:254
2432
+ msgid "Connection"
 
2433
  msgstr ""
2434
 
2435
+ #: includes/Settings.php:271
2436
+ #. translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag
2437
+ msgid "Log debug messages to the %1$sWooCommerce status log%2$s"
2438
  msgstr ""
2439
 
2440
+ #: includes/Settings.php:319
2441
+ msgid "Please choose a location"
 
2442
  msgstr ""
2443
 
2444
+ #: includes/Settings.php:353
2445
+ msgid "Import all products from Square"
 
2446
  msgstr ""
2447
 
2448
+ #: includes/Sync/Interval_Polling.php:98
2449
+ msgid "Updated data for %d category."
2450
+ msgid_plural "Updated data for %d categories."
2451
+ msgstr[0] ""
2452
+ msgstr[1] ""
2453
 
2454
+ #: includes/Sync/Interval_Polling.php:108
2455
+ msgid ""
2456
+ "Product category data could not be updated from Square. Invalid API "
2457
+ "response."
2458
  msgstr ""
2459
 
2460
+ #: includes/Sync/Manual_Synchronization.php:925
2461
+ #. translators: Placeholder: %s - product ID
2462
+ msgid "Product %s could not be updated in Square."
2463
  msgstr ""
2464
 
2465
+ #: includes/Sync/Product_Import.php:546
2466
+ #. translators: Placeholders: %1$s - Square item name, %2$s - Square item
2467
+ #. variation name, %3$s - failure reason
2468
+ msgid "Could not import \"%1$s - %2$s\" from Square. %3$s"
2469
  msgstr ""
2470
 
2471
+ #: includes/Sync/Product_Import.php:591
2472
+ #. translators: Placeholders: %1$s - Square item name, %2$s - failure reason
2473
+ msgid "Could not import \"%1$s\" from Square. %2$s"
2474
  msgstr ""
2475
 
2476
+ #: includes/Sync/Product_Import.php:620
2477
+ msgid "Items with variable pricing cannot be imported."
 
2478
  msgstr ""
2479
 
2480
+ #: includes/Sync/Product_Import.php:624
2481
+ msgid "Variations with missing SKUs cannot be imported."
 
2482
  msgstr ""
2483
 
2484
+ #: includes/Sync/Product_Import.php:717 includes/Sync/Product_Import.php:994
2485
+ msgid "The SKU already exists on another product"
 
2486
  msgstr ""
2487
 
2488
+ #: includes/Sync/Product_Import.php:909
2489
+ #. translators: Placeholders: %1$s - variation ID, %2$s - product name
2490
+ msgid "Variation #%1$s of %2$s"
2491
  msgstr ""
2492
 
2493
+ #: includes/Sync/Product_Import.php:1288
2494
+ #. translators: Placeholders: %s - missing parameter name
2495
+ msgid "Missing parameter %s"
2496
  msgstr ""
2497
 
2498
+ #: includes/Sync/Product_Import.php:1294
2499
+ #. translators: Placeholders: %s - comma separated list of valid product types
2500
+ msgid "Invalid product type - the product type must be any of these: %s"
2501
  msgstr ""
2502
 
2503
+ #: includes/Sync/Product_Import.php:1345
2504
+ #. translators: Placeholders: %1$s - Square item name, %2$s - Failure reason
2505
+ msgid "Could not update %1$s from Square. %2$s"
2506
  msgstr ""
2507
 
2508
+ #: includes/Sync/Product_Import.php:1348
2509
+ #. translators: Placeholders: %1$s - Square item name, %2$s - Failure reason
2510
+ msgid "Could not import %1$s from Square. %2$s"
 
 
 
2511
  msgstr ""
2512
 
2513
+ #: includes/Sync/Records/Record.php:205
2514
+ msgid "Info"
 
 
2515
  msgstr ""
2516
 
2517
+ #: includes/Sync/Records/Record.php:206
2518
+ msgid "Notice"
 
 
 
2519
  msgstr ""
2520
 
2521
+ #: includes/Sync/Records/Record.php:207
2522
+ msgid "Alert"
 
 
 
2523
  msgstr ""
2524
 
2525
+ #: includes/Sync/Records/Record.php:373
2526
+ #. translators: Placeholder: %s - product name
2527
+ msgid "%s not found in Square."
2528
  msgstr ""
2529
 
2530
+ #: includes/Sync/Records/Record.php:552
2531
+ msgid "Ignore"
 
 
2532
  msgstr ""
2533
 
2534
+ #: includes/Sync/Records/Record.php:561
2535
+ msgid "Unlink"
 
 
2536
  msgstr ""
2537
 
2538
+ #: includes/Utilities/Encryption_Utility.php:55
2539
+ msgid "Encryption is not supported on this site."
 
 
 
2540
  msgstr ""
2541
 
2542
+ #: includes/Utilities/Encryption_Utility.php:72
2543
+ msgid "%1$s encryption is not available on this site. %2$s will be used instead."
 
 
 
2544
  msgstr ""
2545
 
2546
+ #: includes/Utilities/Encryption_Utility.php:97
2547
+ msgid "No encryption method available"
 
 
2548
  msgstr ""
2549
 
2550
+ #: includes/Utilities/Encryption_Utility.php:101
2551
+ msgid "Data must be a non-empty string or array"
 
 
2552
  msgstr ""
2553
 
2554
+ #: includes/Utilities/Encryption_Utility.php:105
2555
+ #: includes/Utilities/Encryption_Utility.php:148
2556
+ msgid "Encryption key must be a string"
2557
  msgstr ""
2558
 
2559
+ #: includes/Utilities/Encryption_Utility.php:117
2560
+ msgid "Could not generate encryption vector."
2561
  msgstr ""
2562
 
2563
+ #: includes/Utilities/Encryption_Utility.php:140
2564
+ msgid "No decryption method available"
2565
  msgstr ""
2566
 
2567
+ #: includes/Utilities/Encryption_Utility.php:144
2568
+ msgid "Data must be a non-empty string"
2569
  msgstr ""
2570
 
2571
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ActionFactory.php:161
2572
+ msgid "Invalid action - must be a recurring action."
2573
  msgstr ""
2574
 
2575
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:60
2576
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:75
2577
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:76
2578
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:89
2579
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:19
2580
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:30
2581
+ msgid "Scheduled Actions"
2582
  msgstr ""
2583
 
2584
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:127
2585
+ msgid "About"
2586
  msgstr ""
2587
 
2588
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:129
2589
+ msgid "About Action Scheduler %s"
2590
  msgstr ""
2591
 
2592
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:131
2593
+ msgid ""
2594
+ "Action Scheduler is a scalable, traceable job queue for background "
2595
+ "processing large sets of actions. Action Scheduler works by triggering an "
2596
+ "action hook to run at some time in the future. Scheduled actions can also "
2597
+ "be scheduled to run on a recurring schedule."
2598
  msgstr ""
2599
 
2600
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:139
2601
+ msgid "Columns"
 
 
 
 
 
2602
  msgstr ""
2603
 
2604
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:141
2605
+ msgid "Scheduled Action Columns"
 
 
 
 
2606
  msgstr ""
2607
 
2608
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:143
2609
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:96
2610
+ msgid "Hook"
 
2611
  msgstr ""
2612
 
2613
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:143
2614
+ msgid "Name of the action hook that will be triggered."
 
2615
  msgstr ""
2616
 
2617
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:144
2618
+ msgid "Action statuses are Pending, Complete, Canceled, Failed"
2619
  msgstr ""
2620
 
2621
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:145
2622
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:98
2623
+ msgid "Arguments"
2624
  msgstr ""
2625
 
2626
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:145
2627
+ msgid "Optional data array passed to the action hook."
 
 
2628
  msgstr ""
2629
 
2630
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:146
2631
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:99
2632
+ msgid "Group"
 
2633
  msgstr ""
2634
 
2635
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:146
2636
+ msgid "Optional action group."
 
 
2637
  msgstr ""
2638
 
2639
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:147
2640
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:100
2641
+ msgid "Recurrence"
2642
  msgstr ""
2643
 
2644
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:147
2645
+ msgid "The action's schedule frequency."
2646
  msgstr ""
2647
 
2648
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:148
2649
+ msgid "Scheduled"
2650
  msgstr ""
2651
 
2652
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:148
2653
+ msgid "The date/time the action is/was scheduled to run."
2654
  msgstr ""
2655
 
2656
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:149
2657
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:102
2658
+ msgid "Log"
2659
  msgstr ""
2660
 
2661
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_AdminView.php:149
2662
+ msgid "Activity log for the action."
2663
  msgstr ""
2664
 
2665
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_DataController.php:133
2666
+ #. translators: %d: amount of time
2667
+ msgid "Stopped the insanity for %d second"
2668
+ msgid_plural "Stopped the insanity for %d seconds"
2669
+ msgstr[0] ""
2670
+ msgstr[1] ""
2671
 
2672
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_DataController.php:137
2673
+ msgid "Attempting to reduce used memory..."
 
2674
  msgstr ""
2675
 
2676
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_InvalidActionException.php:21
2677
+ #. translators: 1: action ID 2: schedule
2678
+ msgid "Action [%1$s] has an invalid schedule: %2$s"
2679
  msgstr ""
2680
 
2681
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_InvalidActionException.php:40
2682
+ #. translators: 1: action ID 2: arguments
2683
+ msgid ""
2684
+ "Action [%1$s] has invalid arguments. It cannot be JSON decoded to an array. "
2685
+ "$args = %2$s"
2686
  msgstr ""
2687
 
2688
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:101
2689
+ msgid "Scheduled Date"
 
 
2690
  msgstr ""
2691
 
2692
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:122
2693
+ msgid "Claim ID"
 
 
2694
  msgstr ""
2695
 
2696
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:129
2697
+ msgid "Run"
2698
  msgstr ""
2699
 
2700
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:130
2701
+ msgid "Process the action now as if it were run as part of a queue"
2702
  msgstr ""
2703
 
2704
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:134
2705
+ msgid "Cancel the action now to avoid it being run in future"
2706
  msgstr ""
2707
 
2708
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:144
2709
+ #. translators: %s: amount of time
2710
+ msgid "%s year"
2711
+ msgid_plural "%s years"
2712
+ msgstr[0] ""
2713
+ msgstr[1] ""
2714
 
2715
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:149
2716
+ #. translators: %s: amount of time
2717
+ msgid "%s month"
2718
+ msgid_plural "%s months"
2719
+ msgstr[0] ""
2720
+ msgstr[1] ""
2721
 
2722
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:154
2723
+ #. translators: %s: amount of time
2724
+ msgid "%s week"
2725
+ msgid_plural "%s weeks"
2726
+ msgstr[0] ""
2727
+ msgstr[1] ""
2728
 
2729
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:159
2730
+ #. translators: %s: amount of time
2731
+ msgid "%s day"
2732
+ msgid_plural "%s days"
2733
+ msgstr[0] ""
2734
+ msgstr[1] ""
2735
 
2736
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:164
2737
+ #. translators: %s: amount of time
2738
+ msgid "%s hour"
2739
+ msgid_plural "%s hours"
2740
+ msgstr[0] ""
2741
+ msgstr[1] ""
2742
 
2743
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:169
2744
+ #. translators: %s: amount of time
2745
+ msgid "%s minute"
2746
+ msgid_plural "%s minutes"
2747
+ msgstr[0] ""
2748
+ msgstr[1] ""
2749
 
2750
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:174
2751
+ #. translators: %s: amount of time
2752
+ msgid "%s second"
2753
+ msgid_plural "%s seconds"
2754
+ msgstr[0] ""
2755
+ msgstr[1] ""
2756
 
2757
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:224
2758
+ msgid "Now!"
2759
  msgstr ""
2760
 
2761
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:260
2762
+ #. translators: %s: time interval
2763
+ msgid "Every %s"
2764
  msgstr ""
2765
 
2766
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:266
2767
+ msgid "Non-repeating"
 
 
 
 
2768
  msgstr ""
2769
 
2770
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:364
 
2771
  msgid ""
2772
+ "It appears one or more database tables were missing. Attempting to "
2773
+ "re-create the missing table(s)."
 
 
2774
  msgstr ""
2775
 
2776
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:380
2777
+ #. translators: %s: amount of claims
 
2778
  msgid ""
2779
+ "Maximum simultaneous queues already in progress (%s queue). No additional "
2780
+ "queues will begin processing until the current queues are complete."
2781
  msgid_plural ""
2782
+ "Maximum simultaneous queues already in progress (%s queues). No additional "
2783
+ "queues will begin processing until the current queues are complete."
2784
  msgstr[0] ""
2785
  msgstr[1] ""
2786
 
2787
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:397
2788
+ #. translators: %s: process URL
 
2789
  msgid ""
2790
+ "A new queue has begun processing. <a href=\"%s\">View actions in-progress "
2791
+ "&raquo;</a>"
 
2792
  msgstr ""
2793
 
2794
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:400
2795
+ #. translators: %d: seconds
2796
+ msgid "The next queue will begin processing in approximately %d seconds."
 
 
 
2797
  msgstr ""
2798
 
2799
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:421
2800
+ #. translators: %s: action HTML
2801
+ msgid "Successfully executed action: %s"
 
 
 
2802
  msgstr ""
2803
 
2804
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:425
2805
+ #. translators: %s: action HTML
2806
+ msgid "Successfully canceled action: %s"
 
2807
  msgstr ""
2808
 
2809
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:429
2810
+ #. translators: %s: action HTML
2811
+ msgid "Successfully processed change for action: %s"
2812
  msgstr ""
2813
 
2814
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:435
2815
+ #. translators: 1: action HTML 2: action ID 3: error message
2816
+ msgid "Could not process change for action: \"%1$s\" (ID: %2$d). Error: %3$s"
2817
  msgstr ""
2818
 
2819
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:481
2820
+ #. translators: %s: date interval
2821
+ msgid " (%s ago)"
2822
  msgstr ""
2823
 
2824
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:484
2825
+ #. translators: %s: date interval
2826
+ msgid " (%s)"
2827
  msgstr ""
2828
 
2829
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_ListTable.php:634
2830
+ msgid "Search hook, args and claim ID"
2831
  msgstr ""
2832
 
2833
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_QueueRunner.php:192
2834
+ msgid "Every minute"
2835
  msgstr ""
2836
 
2837
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php:103
2838
+ #. translators: %s: date interval
2839
+ msgid "This data will be deleted in %s."
2840
  msgstr ""
2841
 
2842
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php:108
2843
+ #. translators: 1: next cleanup message 2: github issue URL
2844
+ msgid ""
2845
+ "Action Scheduler has migrated data to custom tables; however, orphaned log "
2846
+ "entries exist in the WordPress Comments table. %1$s <a href=\"%2$s\">Learn "
2847
+ "more &raquo;</a>"
2848
  msgstr ""
2849
 
2850
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:111
2851
+ msgid "Action Scheduler"
2852
  msgstr ""
2853
 
2854
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:111
2855
+ msgid "This section shows details of Action Scheduler."
2856
  msgstr ""
2857
 
2858
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:114
2859
+ msgid "Version:"
2860
  msgstr ""
2861
 
2862
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:118
2863
+ msgid "Data store:"
2864
  msgstr ""
2865
 
2866
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:122
2867
+ msgid "Action Status"
2868
  msgstr ""
2869
 
2870
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:124
2871
+ msgid "Count"
2872
  msgstr ""
2873
 
2874
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:125
2875
+ msgid "Oldest Scheduled Date"
2876
  msgstr ""
2877
 
2878
+ #: vendor/woocommerce/action-scheduler/classes/ActionScheduler_wcSystemStatus.php:126
2879
+ msgid "Newest Scheduled Date"
2880
+ msgstr ""
2881
+
2882
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:33
2883
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ProgressBar.php:47
2884
+ #. translators: %s php class name
2885
+ msgid "The %s class can only be run within WP CLI."
2886
+ msgstr ""
2887
+
2888
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:59
2889
+ msgid "There are too many concurrent batches, but the run is forced to continue."
2890
+ msgstr ""
2891
+
2892
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:61
2893
+ msgid "There are too many concurrent batches."
2894
+ msgstr ""
2895
+
2896
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:93
2897
+ #. translators: %d: amount of actions
2898
+ msgid "Running %d action"
2899
+ msgid_plural "Running %d actions"
2900
+ msgstr[0] ""
2901
+ msgstr[1] ""
2902
+
2903
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:113
2904
+ msgid "The claim has been lost. Aborting current batch."
2905
+ msgstr ""
2906
+
2907
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:138
2908
+ #. translators: %s refers to the action ID
2909
+ msgid "Started processing action %s"
2910
  msgstr ""
2911
 
2912
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:155
2913
+ #. translators: 1: action ID 2: hook name
2914
+ msgid "Completed processing action %1$s with hook: %2$s"
2915
  msgstr ""
2916
 
2917
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_QueueRunner.php:170
2918
+ #. translators: 1: action ID 2: exception message
2919
+ msgid "Error processing action %1$s: %2$s"
2920
  msgstr ""
2921
 
2922
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php:100
2923
+ #. translators: %d refers to how many scheduled taks were found to run
2924
+ msgid "Found %d scheduled task"
2925
+ msgid_plural "Found %d scheduled tasks"
2926
+ msgstr[0] ""
2927
+ msgstr[1] ""
2928
 
2929
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php:117
2930
+ #. translators: %d refers to the total number of batches executed
2931
+ msgid "%d batch executed."
2932
+ msgid_plural "%d batches executed."
2933
+ msgstr[0] ""
2934
+ msgstr[1] ""
2935
+
2936
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php:136
2937
+ #. translators: %s refers to the exception error message
2938
+ msgid "There was an error running the action scheduler: %s"
2939
  msgstr ""
2940
 
2941
+ #: vendor/woocommerce/action-scheduler/classes/WP_CLI/ActionScheduler_WPCLI_Scheduler_command.php:153
2942
+ #. translators: %d refers to the total number of taskes completed
2943
+ msgid "%d scheduled task completed."
2944
+ msgid_plural "%d scheduled tasks completed."
2945
+ msgstr[0] ""
2946
+ msgstr[1] ""
2947
+
2948
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler.php:195
2949
+ msgid "%s() was called before the Action Scheduler data store was initialized"
2950
  msgstr ""
2951
 
2952
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php:523
2953
+ msgid "Filter"
2954
  msgstr ""
2955
 
2956
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php:650
2957
+ #. translators: %s: search query
2958
+ msgid "Search results for \"%s\""
2959
  msgstr ""
2960
 
2961
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php:755
2962
+ msgid "Search"
 
2963
  msgstr ""
2964
 
2965
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:72
2966
+ msgid "action created"
 
 
2967
  msgstr ""
2968
 
2969
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:76
2970
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php:142
2971
+ msgid "action canceled"
2972
  msgstr ""
2973
 
2974
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:82
2975
+ #. translators: %s: context
2976
+ msgid "action started via %s"
 
2977
  msgstr ""
2978
 
2979
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:84
2980
+ msgid "action started"
 
 
2981
  msgstr ""
2982
 
2983
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:92
2984
+ #. translators: %s: context
2985
+ msgid "action complete via %s"
 
2986
  msgstr ""
2987
 
2988
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:94
2989
+ msgid "action complete"
 
 
2990
  msgstr ""
2991
 
2992
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:102
2993
+ #. translators: 1: context 2: exception message
2994
+ msgid "action failed via %1$s: %2$s"
 
2995
  msgstr ""
2996
 
2997
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:105
2998
+ #. translators: %s: exception message
2999
+ msgid "action failed: %s"
 
3000
  msgstr ""
3001
 
3002
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:112
3003
+ #. translators: %s: amount of time
3004
+ msgid "action timed out after %s seconds"
 
3005
  msgstr ""
3006
 
3007
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:118
3008
+ #. translators: 1: error message 2: filename 3: line
3009
+ msgid "unexpected shutdown: PHP Fatal error %1$s in %2$s on line %3$s"
 
3010
  msgstr ""
3011
 
3012
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:123
3013
+ msgid "action reset"
 
 
3014
  msgstr ""
3015
 
3016
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:129
3017
+ #. translators: %s: context
3018
+ msgid "action ignored via %s"
 
3019
  msgstr ""
3020
 
3021
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:131
3022
+ msgid "action ignored"
 
 
3023
  msgstr ""
3024
 
3025
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:146
3026
+ #. translators: %s: exception message
3027
+ msgid "There was a failure fetching this action: %s"
 
3028
  msgstr ""
3029
 
3030
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:148
3031
+ msgid "There was a failure fetching this action"
 
 
3032
  msgstr ""
3033
 
3034
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Logger.php:156
3035
+ #. translators: %s: exception message
3036
+ msgid "There was a failure scheduling the next instance of this action: %s"
3037
  msgstr ""
3038
 
3039
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:301
3040
  msgid ""
3041
+ "ActionScheduler_Action::$args too long. To ensure the args column can be "
3042
+ "indexed, action args should not be more than %d characters when encoded as "
3043
+ "JSON."
3044
  msgstr ""
3045
 
3046
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:377
3047
+ msgid "Complete"
3048
  msgstr ""
3049
 
3050
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:379
3051
+ msgid "In-progress"
 
 
3052
  msgstr ""
3053
 
3054
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:380
3055
+ msgid "Failed"
3056
  msgstr ""
3057
 
3058
+ #: vendor/woocommerce/action-scheduler/classes/abstracts/ActionScheduler_Store.php:381
3059
+ msgid "Canceled"
3060
  msgstr ""
3061
 
3062
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:78
3063
+ msgid "Database error."
3064
  msgstr ""
3065
 
3066
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:86
3067
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:49
3068
+ #: vendor/woocommerce/action-scheduler/classes/migration/ActionScheduler_DBStoreMigrator.php:44
3069
+ #. translators: %s: error message
3070
+ #. translators: %s: action error message
3071
+ msgid "Error saving action: %s"
3072
  msgstr ""
3073
 
3074
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:246
3075
+ msgid "Invalid value for select or count parameter. Cannot query actions."
3076
  msgstr ""
3077
 
3078
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:451
3079
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:543
3080
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:574
3081
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:797
3082
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:840
3083
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:515
3084
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:534
3085
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:564
3086
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:974
3087
+ #. translators: %s: action ID
3088
+ #. translators: %s is the action ID
3089
+ msgid "Unidentified action %s"
3090
  msgstr ""
3091
 
3092
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:663
3093
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:717
3094
+ #. translators: %s: group name
3095
+ #. translators: %s is the group name
3096
+ msgid "The group \"%s\" does not exist."
3097
  msgstr ""
3098
 
3099
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:683
3100
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:696
3101
+ msgid "Unable to claim actions. Database error."
 
 
3102
  msgstr ""
3103
 
3104
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:861
3105
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:904
3106
+ msgid "Invalid action ID. No status found."
 
 
3107
  msgstr ""
3108
 
3109
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBStore.php:863
3110
+ msgid "Unknown status found for action."
3111
  msgstr ""
3112
 
3113
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:101
3114
+ msgid "Unable to save action."
3115
  msgstr ""
3116
 
3117
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:318
3118
+ msgid "Invalid schedule. Cannot save action."
3119
  msgstr ""
3120
 
3121
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:824
3122
+ #. translators: %s: claim ID
3123
+ msgid "Unable to unlock claim %s. Database error."
3124
  msgstr ""
3125
 
3126
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:852
3127
+ #. translators: %s: action ID
3128
+ msgid "Unable to unlock claim on action %s. Database error."
3129
  msgstr ""
3130
 
3131
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:878
3132
+ #. translators: %s: action ID
3133
+ msgid "Unable to mark failure on action %s. Database error."
3134
  msgstr ""
3135
 
3136
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php:1046
3137
+ #. translators: %s is the error message
3138
+ msgid "%s Support for strings longer than this will be removed in a future version."
3139
  msgstr ""
3140
 
3141
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php:38
3142
+ #. translators: %s: count
3143
+ msgid "Failed <span class=\"count\">(%s)</span>"
3144
+ msgid_plural "Failed <span class=\"count\">(%s)</span>"
3145
+ msgstr[0] ""
3146
+ msgstr[1] ""
3147
+
3148
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php:53
3149
+ #. translators: %s: count
3150
+ msgid "In-Progress <span class=\"count\">(%s)</span>"
3151
+ msgid_plural "In-Progress <span class=\"count\">(%s)</span>"
3152
+ msgstr[0] ""
3153
+ msgstr[1] ""
3154
+
3155
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:20
3156
+ msgid "Scheduled actions are hooks triggered on a cetain date and time."
3157
  msgstr ""
3158
 
3159
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:31
3160
+ msgid "Scheduled Action"
3161
  msgstr ""
3162
 
3163
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:33
3164
+ msgid "Add"
 
 
3165
  msgstr ""
3166
 
3167
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:34
3168
+ msgid "Add New Scheduled Action"
3169
  msgstr ""
3170
 
3171
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:36
3172
+ msgid "Edit Scheduled Action"
3173
  msgstr ""
3174
 
3175
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:37
3176
+ msgid "New Scheduled Action"
 
 
3177
  msgstr ""
3178
 
3179
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:38
3180
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:39
3181
+ msgid "View Action"
3182
  msgstr ""
3183
 
3184
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:40
3185
+ msgid "Search Scheduled Actions"
 
3186
  msgstr ""
3187
 
3188
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:41
3189
+ msgid "No actions found"
3190
  msgstr ""
3191
 
3192
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:42
3193
+ msgid "No actions found in trash"
3194
  msgstr ""
3195
 
3196
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php:14
3197
+ msgid "Action Group"
3198
  msgstr ""
3199
 
3200
+ #: vendor/woocommerce/action-scheduler/classes/migration/ActionMigrator.php:95
3201
+ msgid "Unable to remove source migrated action %s"
3202
  msgstr ""
3203
 
3204
+ #: vendor/woocommerce/action-scheduler/classes/migration/Config.php:52
3205
+ msgid "Source store must be configured before running a migration"
3206
  msgstr ""
3207
 
3208
+ #: vendor/woocommerce/action-scheduler/classes/migration/Config.php:74
3209
+ msgid "Source logger must be configured before running a migration"
3210
  msgstr ""
3211
 
3212
+ #: vendor/woocommerce/action-scheduler/classes/migration/Config.php:96
3213
+ msgid "Destination store must be configured before running a migration"
 
 
3214
  msgstr ""
3215
 
3216
+ #: vendor/woocommerce/action-scheduler/classes/migration/Config.php:118
3217
+ msgid "Destination logger must be configured before running a migration"
3218
  msgstr ""
3219
 
3220
+ #: vendor/woocommerce/action-scheduler/classes/migration/Controller.php:162
3221
  msgid ""
3222
+ "Action Scheduler migration in progress. The list of scheduled actions may "
3223
+ "be incomplete."
3224
  msgstr ""
3225
 
3226
+ #: vendor/woocommerce/action-scheduler/classes/migration/Runner.php:82
3227
+ #. translators: %d: amount of actions
3228
+ msgid "Migrating %d action"
3229
+ msgid_plural "Migrating %d actions"
3230
+ msgstr[0] ""
3231
+ msgstr[1] ""
3232
+
3233
+ #: vendor/woocommerce/action-scheduler/classes/migration/Runner.php:107
3234
+ #. translators: 1: source action ID 2: source store class 3: destination action
3235
+ #. ID 4: destination store class
3236
+ msgid "Migrated action with ID %1$d in %2$s to ID %3$d in %4$s"
3237
  msgstr ""
3238
 
3239
  #. Plugin URI of the plugin/theme
3250
  msgid "https://www.woocommerce.com/"
3251
  msgstr ""
3252
 
3253
+ #: includes/Admin/Sync_Page.php:286
3254
  msgctxt "Delete all records"
3255
  msgid "Clear history"
3256
  msgstr ""
3257
 
3258
+ #: includes/Admin/Sync_Page.php:291 includes/Admin/Sync_Page.php:332
3259
  msgctxt "Date - Time"
3260
  msgid "Time"
3261
  msgstr ""
3262
 
3263
+ #: includes/Emails/Access_Token_Email.php:45
3264
  msgctxt "Email subject"
3265
  msgid "[WooCommerce] There was a problem with your Square Access Token"
3266
  msgstr ""
3267
 
3268
+ #: includes/Emails/Sync_Completed.php:35
3269
  msgctxt "Email subject"
3270
  msgid "[WooCommerce] Square sync completed"
3271
  msgstr ""
3272
 
3273
+ #: includes/Emails/Access_Token_Email.php:46
3274
  msgctxt "Email heading"
3275
  msgid "There was a problem with your Square Access Token"
3276
  msgstr ""
3277
 
3278
+ #: includes/Emails/Access_Token_Email.php:47
3279
  msgctxt "Square connection problems email body."
3280
  msgid "Heads up! There may be a problem with your connection to Square."
3281
  msgstr ""
3282
 
3283
+ #: includes/Emails/Sync_Completed.php:36
3284
  msgctxt "Email heading with merge tag placeholder"
3285
  msgid "Square sync completed for {product_count}"
3286
  msgstr ""
3287
 
3288
+ #: includes/Emails/Sync_Completed.php:37
3289
  msgctxt "Email body with merge tag placeholders"
3290
  msgid ""
3291
  "Square sync completed for {site_title} at {sync_completed_date} "
3292
  "{sync_completed_time}."
3293
  msgstr ""
3294
 
3295
+ #: includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php:545
3296
+ msgctxt "hash before order number"
3297
+ msgid "#%s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3298
  msgstr ""
3299
 
3300
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2155
3301
+ msgctxt "hash before order number"
3302
+ msgid "#"
3303
  msgstr ""
3304
 
3305
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2360
3306
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:565
3307
  msgctxt "noun, software environment"
3308
  msgid "Test"
3309
  msgstr ""
3310
 
3311
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2361
3312
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2761
3313
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:566
3314
  msgctxt "credit card transaction type"
3315
  msgid "Authorization"
3316
  msgstr ""
3317
 
3318
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2361
3319
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2760
3320
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Direct.php:566
3321
  msgctxt "noun, credit card transaction type"
3322
  msgid "Charge"
3323
  msgstr ""
3324
 
3325
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:2789
3326
+ msgctxt ""
3327
+ "coordinating conjunction for a list of order statuses: on-hold, processing, "
3328
+ "or completed"
3329
+ msgid "or"
3330
  msgstr ""
3331
 
3332
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3019
3333
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:201
3334
  msgctxt "credit card type"
3335
  msgid "Visa"
3336
  msgstr ""
3337
 
3338
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3020
3339
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:205
3340
  msgctxt "credit card type"
3341
  msgid "MasterCard"
3342
  msgstr ""
3343
 
3344
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3021
3345
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:209
3346
  msgctxt "credit card type"
3347
  msgid "American Express"
3348
  msgstr ""
3349
 
3350
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3022
3351
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:217
3352
  msgctxt "credit card type"
3353
+ msgid "Discover"
3354
  msgstr ""
3355
 
3356
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3023
 
3357
  msgctxt "credit card type"
3358
+ msgid "Diners"
3359
  msgstr ""
3360
 
3361
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3024
3362
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:221
3363
  msgctxt "credit card type"
3364
  msgid "JCB"
3365
  msgstr ""
3366
 
3367
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:213
3368
+ msgctxt "credit card type"
3369
+ msgid "Diners Club"
3370
+ msgstr ""
3371
+
3372
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:225
3373
  msgctxt "credit card type"
3374
  msgid "CarteBleue"
3375
  msgstr ""
3376
 
3377
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:229
3378
  msgctxt "credit card type"
3379
  msgid "Maestro"
3380
  msgstr ""
3381
 
3382
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:233
3383
  msgctxt "credit card type"
3384
  msgid "Laser"
3385
  msgstr ""
3386
 
3387
+ #: includes/Framework/PaymentGateway/Payment_Gateway.php:3509
3388
+ msgctxt "software environment"
3389
+ msgid "Production"
3390
  msgstr ""
3391
 
3392
+ #: includes/Framework/PaymentGateway/Payment_Gateway_Helper.php:165
3393
+ msgctxt "payment method type"
3394
+ msgid "Account"
 
3395
  msgstr ""
3396
 
3397
+ #: includes/Framework/Plugin.php:353
3398
+ msgctxt "noun"
3399
+ msgid "Support"
 
3400
  msgstr ""
3401
 
3402
+ #: includes/Framework/Plugin.php:358
3403
+ msgctxt "verb"
3404
+ msgid "Review"
3405
  msgstr ""
3406
 
3407
+ #: includes/Framework/Square_Helper.php:218
3408
+ #: includes/Utilities/Array_Utility.php:90
3409
+ msgctxt "coordinating conjunction for a list of items: a, b, and c"
3410
+ msgid "and"
3411
  msgstr ""
3412
 
3413
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php:36
3414
+ msgctxt "post"
3415
+ msgid "Failed"
 
 
3416
  msgstr ""
3417
 
3418
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostStatusRegistrar.php:51
3419
+ msgctxt "post"
3420
+ msgid "In-Progress"
3421
+ msgstr ""
3422
+
3423
+ #: vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php:32
3424
+ msgctxt "Admin menu name"
3425
+ msgid "Scheduled Actions"
3426
  msgstr ""
includes/AJAX.php CHANGED
@@ -25,9 +25,7 @@ namespace WooCommerce\Square;
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
29
  use WooCommerce\Square\Handlers\Product;
30
- use WooCommerce\Square\Handlers\Sync;
31
  use WooCommerce\Square\Sync\Records;
32
 
33
  /**
@@ -63,41 +61,6 @@ class AJAX {
63
  add_action( 'wp_ajax_wc_square_get_sync_with_square_status', array( $this, 'get_sync_with_square_job_status' ) );
64
  }
65
 
66
-
67
- /**
68
- * Checks if a product is set to be synced with Square.
69
- *
70
- * @internal
71
- *
72
- * @since 2.0.0
73
- *
74
- * @deprecated 2.1.6
75
- */
76
- public function is_product_synced_with_square() {
77
- _deprecated_function( 'is_product_synced_with_square', '2.1.6', 'get_quick_edit_product_details' );
78
-
79
- check_ajax_referer( 'is-product-synced-with-square', 'security' );
80
-
81
- if ( isset( $_POST['product_id'] ) && ( $product = wc_get_product( $_POST['product_id'] ) ) ) {
82
-
83
- if ( $product->is_type( 'variable' ) && $product->has_child() ) {
84
- if ( Product::has_multiple_variation_attributes( $product ) ) {
85
- wp_send_json_error( 'multiple_attributes' );
86
- } elseif ( ! Product::has_sku( $product ) ) {
87
- wp_send_json_error( 'missing_variation_sku' );
88
- }
89
- } else {
90
- if ( ! Product::has_sku( $product ) ) {
91
- wp_send_json_error( 'missing_sku' );
92
- }
93
- }
94
- wp_send_json_success( Product::is_synced_with_square( $product ) ? 'yes' : 'no' );
95
- }
96
-
97
- wp_send_json_error( 'invalid_product' );
98
- }
99
-
100
-
101
  /**
102
  * Fetches product stock data from Square.
103
  *
@@ -119,7 +82,7 @@ class AJAX {
119
 
120
  wp_send_json_success( $product->get_stock_quantity() );
121
 
122
- } catch ( Framework\SV_WC_Plugin_Exception $exception ) {
123
 
124
  /* translators: Placeholders: %1$s = error message, %2$s = help text */
125
  wp_send_json_error( sprintf( __( 'Unable to fetch inventory: %1$s. %2$s', 'woocommerce-square' ), $exception->getMessage(), $fix_error ) );
@@ -142,7 +105,7 @@ class AJAX {
142
 
143
  check_ajax_referer( 'import-products-from-square', 'security' );
144
 
145
- $started = wc_square()->get_sync_handler()->start_product_import( ! empty( $_POST['dispatch'] ), ( ! empty( $_POST['update_during_import'] ) && 'true' === $_POST['update_during_import'] ) );
146
 
147
  if ( ! $started ) {
148
  wp_send_json_error( __( 'Could not start import. Please try again.', 'woocommerce-square' ) );
@@ -163,7 +126,7 @@ class AJAX {
163
 
164
  check_ajax_referer( 'sync-products-with-square', 'security' );
165
 
166
- $started = wc_square()->get_sync_handler()->start_manual_sync( ! empty( $_POST['dispatch'] ) );
167
 
168
  if ( ! $started ) {
169
  wp_send_json_error();
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
 
28
  use WooCommerce\Square\Handlers\Product;
 
29
  use WooCommerce\Square\Sync\Records;
30
 
31
  /**
61
  add_action( 'wp_ajax_wc_square_get_sync_with_square_status', array( $this, 'get_sync_with_square_job_status' ) );
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  /**
65
  * Fetches product stock data from Square.
66
  *
82
 
83
  wp_send_json_success( $product->get_stock_quantity() );
84
 
85
+ } catch ( \Exception $exception ) {
86
 
87
  /* translators: Placeholders: %1$s = error message, %2$s = help text */
88
  wp_send_json_error( sprintf( __( 'Unable to fetch inventory: %1$s. %2$s', 'woocommerce-square' ), $exception->getMessage(), $fix_error ) );
105
 
106
  check_ajax_referer( 'import-products-from-square', 'security' );
107
 
108
+ $started = wc_square()->get_sync_handler()->start_product_import( ( ! empty( $_POST['update_during_import'] ) && 'true' === $_POST['update_during_import'] ) );
109
 
110
  if ( ! $started ) {
111
  wp_send_json_error( __( 'Could not start import. Please try again.', 'woocommerce-square' ) );
126
 
127
  check_ajax_referer( 'sync-products-with-square', 'security' );
128
 
129
+ $started = wc_square()->get_sync_handler()->start_manual_sync();
130
 
131
  if ( ! $started ) {
132
  wp_send_json_error();
includes/API.php CHANGED
@@ -23,10 +23,11 @@
23
 
24
  namespace WooCommerce\Square;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect;
28
  use WooCommerce\Square\API\Requests;
29
  use WooCommerce\Square\API\Responses;
 
 
30
 
31
  defined( 'ABSPATH' ) || exit;
32
 
@@ -35,7 +36,7 @@ defined( 'ABSPATH' ) || exit;
35
  *
36
  * @since 2.0.0
37
  */
38
- class API extends Framework\SV_WC_API_Base {
39
 
40
 
41
  /** catalog request type */
@@ -45,7 +46,7 @@ class API extends Framework\SV_WC_API_Base {
45
  const REQUEST_TYPE_INVENTORY = 'inventory';
46
 
47
 
48
- /** @var SquareConnect\ApiClient Square API client instance */
49
  protected $client;
50
 
51
 
@@ -58,15 +59,10 @@ class API extends Framework\SV_WC_API_Base {
58
  * @param bool $is_sandbox If sandbox access is desired
59
  */
60
  public function __construct( $access_token, $is_sandbox = null ) {
61
- $api_config = SquareConnect\Configuration::getDefaultConfiguration();
62
- $api_config->setAccessToken( $access_token );
63
-
64
- // Set sandbox URL if enabled.
65
- if ( $is_sandbox ) {
66
- $api_config->setHost( 'https://connect.squareupsandbox.com' );
67
- }
68
-
69
- $this->client = new SquareConnect\ApiClient( $api_config );
70
  }
71
 
72
 
@@ -80,7 +76,7 @@ class API extends Framework\SV_WC_API_Base {
80
  *
81
  * @param string[] $object_ids array of square catalog object IDs
82
  * @return Responses\Catalog
83
- * @throws Framework\SV_WC_API_Exception
84
  */
85
  public function batch_delete_catalog_objects( array $object_ids ) {
86
 
@@ -99,7 +95,7 @@ class API extends Framework\SV_WC_API_Base {
99
  * @param string[] $object_ids array of square catalog object IDs
100
  * @param bool $include_related_objects whether or not to include related objects in the response
101
  * @return Responses\Catalog
102
- * @throws Framework\SV_WC_API_Exception
103
  */
104
  public function batch_retrieve_catalog_objects( array $object_ids, $include_related_objects = false ) {
105
 
@@ -118,7 +114,7 @@ class API extends Framework\SV_WC_API_Base {
118
  * @param string $idempotency_key a UUID for this request
119
  * @param array $batches an array of batches to upsert
120
  * @return Responses\Catalog
121
- * @throws Framework\SV_WC_API_Exception
122
  */
123
  public function batch_upsert_catalog_objects( $idempotency_key, array $batches ) {
124
 
@@ -134,7 +130,7 @@ class API extends Framework\SV_WC_API_Base {
134
  *
135
  * @since 2.0.0
136
  * @return Responses\Catalog
137
- * @throws Framework\SV_WC_API_Exception
138
  */
139
  public function catalog_info() {
140
 
@@ -152,7 +148,7 @@ class API extends Framework\SV_WC_API_Base {
152
  *
153
  * @param string $object_id Square catalog object ID
154
  * @return Responses\Catalog
155
- * @throws Framework\SV_WC_API_Exception
156
  */
157
  public function delete_catalog_object( $object_id ) {
158
 
@@ -171,7 +167,7 @@ class API extends Framework\SV_WC_API_Base {
171
  * @param string $cursor the cursor to list from
172
  * @param string[] $types the item types to filter by
173
  * @return Responses\Catalog
174
- * @throws Framework\SV_WC_API_Exception
175
  */
176
  public function list_catalog( $cursor = '', $types = array() ) {
177
 
@@ -190,7 +186,7 @@ class API extends Framework\SV_WC_API_Base {
190
  * @param string $object_id the Square catalog object ID
191
  * @param bool $include_related_objects whether or not to include related objects (such as categories)
192
  * @return Responses\Catalog
193
- * @throws Framework\SV_WC_API_Exception
194
  */
195
  public function retrieve_catalog_object( $object_id, $include_related_objects = false ) {
196
 
@@ -208,7 +204,7 @@ class API extends Framework\SV_WC_API_Base {
208
  *
209
  * @param array $args see Catalog::set_search_catalog_objects_data() for list of args
210
  * @return Responses\Catalog
211
- * @throws Framework\SV_WC_API_Exception
212
  */
213
  public function search_catalog_objects( $args = array() ) {
214
 
@@ -228,7 +224,7 @@ class API extends Framework\SV_WC_API_Base {
228
  * @param string[] $modifier_lists_to_enable (optional) modifier list IDs to enable
229
  * @param string[] $modifier_lists_to_disable (optional) modifier list IDs to disable
230
  * @return Responses\Catalog
231
- * @throws Framework\SV_WC_API_Exception
232
  */
233
  public function update_item_modifier_lists( array $item_ids, array $modifier_lists_to_enable = array(), array $modifier_lists_to_disable = array() ) {
234
 
@@ -248,7 +244,7 @@ class API extends Framework\SV_WC_API_Base {
248
  * @param string[] $taxes_to_enable (optional) tax IDs to enable
249
  * @param string[] $taxes_to_disable (optional) tax IDs to disable
250
  * @return Responses\Catalog
251
- * @throws Framework\SV_WC_API_Exception
252
  */
253
  public function update_item_taxes( array $item_ids, array $taxes_to_enable = array(), array $taxes_to_disable = array() ) {
254
 
@@ -265,9 +261,9 @@ class API extends Framework\SV_WC_API_Base {
265
  * @since 2.0.0
266
  *
267
  * @param string $idempotency_key UUID for this request
268
- * @param SquareConnect\Model\CatalogObject $object the object to upsert
269
  * @return Responses\Catalog
270
- * @throws Framework\SV_WC_API_Exception
271
  */
272
  public function upsert_catalog_object( $idempotency_key, $object ) {
273
 
@@ -289,12 +285,12 @@ class API extends Framework\SV_WC_API_Base {
289
  * @param string $square_item_id
290
  * @param string $caption optional image caption
291
  * @return string
292
- * @throws Framework\SV_WC_API_Exception
293
  */
294
  public function create_image( $image_path, $square_item_id = '', $caption = '' ) {
295
 
296
  if ( ! is_readable( $image_path ) ) {
297
- throw new Framework\SV_WC_API_Exception( 'Image file is not readable' );
298
  }
299
 
300
  $image = file_get_contents( $image_path );
@@ -335,7 +331,7 @@ class API extends Framework\SV_WC_API_Base {
335
  $body .= $image . "\r\n";
336
  $body .= '--boundary--';
337
 
338
- $url = $this->client->getConfig()->getHost() . '/v2/catalog/images';
339
 
340
  $response = wp_remote_post(
341
  $url,
@@ -346,14 +342,14 @@ class API extends Framework\SV_WC_API_Base {
346
  );
347
 
348
  if ( is_wp_error( $response ) ) {
349
- throw new Framework\SV_WC_API_Exception( $response->get_error_message() );
350
  }
351
 
352
  $body = wp_remote_retrieve_body( $response );
353
  $body = json_decode( $body, true );
354
 
355
  if ( ! is_array( $body ) ) {
356
- throw new Framework\SV_WC_API_Exception( 'Response was malformed' );
357
  }
358
 
359
  if ( ! empty( $body['errors'] ) || empty( $body['image']['id'] ) ) {
@@ -364,7 +360,7 @@ class API extends Framework\SV_WC_API_Base {
364
  $message = 'Unknown error';
365
  }
366
 
367
- throw new Framework\SV_WC_API_Exception( $message );
368
  }
369
 
370
  return $body['image']['id'];
@@ -382,7 +378,7 @@ class API extends Framework\SV_WC_API_Base {
382
  * @param string $square_id Square object ID
383
  * @param int $amount amount of inventory to add
384
  * @return Responses\Inventory
385
- * @throws Framework\SV_WC_API_Exception
386
  */
387
  public function add_inventory_from_refund( $square_id, $amount ) {
388
 
@@ -399,7 +395,7 @@ class API extends Framework\SV_WC_API_Base {
399
  * @param int $amount amount of inventory to add
400
  * @param string $from_state the API state the inventory is coming from
401
  * @return Responses\Inventory
402
- * @throws Framework\SV_WC_API_Exception
403
  */
404
  public function add_inventory( $square_id, $amount, $from_state = 'NONE' ) {
405
 
@@ -415,7 +411,7 @@ class API extends Framework\SV_WC_API_Base {
415
  * @param string $square_id Square object ID
416
  * @param int $amount amount of inventory to remove
417
  * @return Responses\Inventory
418
- * @throws Framework\SV_WC_API_Exception
419
  */
420
  public function remove_inventory( $square_id, $amount ) {
421
 
@@ -433,26 +429,24 @@ class API extends Framework\SV_WC_API_Base {
433
  * @param string $from_state the API state the inventory is coming from
434
  * @param string $to_state the API state the inventory is changing to
435
  * @return Responses\Inventory
436
- * @throws Framework\SV_WC_API_Exception
437
  */
438
  protected function adjust_inventory( $square_id, $amount, $from_state, $to_state ) {
439
 
440
  $date = new \DateTime();
441
 
442
- $change = new SquareConnect\Model\InventoryChange();
443
  $change->setType( 'ADJUSTMENT' );
444
- $change->setAdjustment(
445
- new SquareConnect\Model\InventoryAdjustment(
446
- array(
447
- 'catalog_object_id' => $square_id,
448
- 'location_id' => $this->get_plugin()->get_settings_handler()->get_location_id(),
449
- 'quantity' => (string) absint( $amount ),
450
- 'from_state' => $from_state,
451
- 'to_state' => $to_state,
452
- 'occurred_at' => $date->format( DATE_ATOM ),
453
- )
454
- )
455
- );
456
 
457
  return $this->batch_change_inventory(
458
  uniqid( '', false ),
@@ -469,10 +463,10 @@ class API extends Framework\SV_WC_API_Base {
469
  * @since 2.0.0
470
  *
471
  * @param string $idempotency_key UUID for this request
472
- * @param SquareConnect\Model\InventoryChange[] $changes array of Inventory Changes
473
  * @param bool $ignore_unchanged_counts whether the current physical count should be ignored if the quantity is unchanged since the last physical count
474
  * @return Responses\Inventory
475
- * @throws Framework\SV_WC_API_Exception
476
  */
477
  public function batch_change_inventory( $idempotency_key, $changes, $ignore_unchanged_counts = true ) {
478
 
@@ -491,7 +485,7 @@ class API extends Framework\SV_WC_API_Base {
491
  * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_changes_data() for accepted arguments
492
  *
493
  * @return Responses\Inventory
494
- * @throws Framework\SV_WC_API_Exception
495
  */
496
  public function batch_retrieve_inventory_changes( array $args = array() ) {
497
 
@@ -510,7 +504,7 @@ class API extends Framework\SV_WC_API_Base {
510
  * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_counts_data() for accepted arguments
511
  *
512
  * @return Responses\Inventory
513
- * @throws Framework\SV_WC_API_Exception
514
  */
515
  public function batch_retrieve_inventory_counts( array $args = array() ) {
516
 
@@ -529,7 +523,7 @@ class API extends Framework\SV_WC_API_Base {
529
  * @param string $adjustment_id the InventoryAdjustment ID to retrieve
530
  *
531
  * @return Responses\Inventory
532
- * @throws Framework\SV_WC_API_Exception
533
  */
534
  public function retrieve_inventory_adjustment( $adjustment_id ) {
535
 
@@ -548,7 +542,7 @@ class API extends Framework\SV_WC_API_Base {
548
  * @param string $catalog_object_id the CatalogObject ID to retrieve
549
  *
550
  * @return Responses\Inventory
551
- * @throws Framework\SV_WC_API_Exception
552
  */
553
  public function retrieve_inventory_changes( $catalog_object_id ) {
554
 
@@ -566,12 +560,12 @@ class API extends Framework\SV_WC_API_Base {
566
  *
567
  * @param string $catalog_object_id the CatalogObject ID to retrieve
568
  * @return Responses\Inventory
569
- * @throws Framework\SV_WC_API_Exception
570
  */
571
  public function retrieve_inventory_count( $catalog_object_id ) {
572
 
573
  $request = $this->get_inventory_request();
574
- $request->set_retrieve_inventory_count_data( $catalog_object_id, array( $this->get_plugin()->get_settings_handler()->get_location_id() ) );
575
 
576
  return $this->perform_request( $request );
577
  }
@@ -585,7 +579,7 @@ class API extends Framework\SV_WC_API_Base {
585
  * @param string $physical_count_id the InventoryPhysicalCount ID to retrieve
586
  *
587
  * @return Responses\Inventory
588
- * @throws Framework\SV_WC_API_Exception
589
  */
590
  public function retrieve_inventory_physical_count( $physical_count_id ) {
591
 
@@ -604,8 +598,8 @@ class API extends Framework\SV_WC_API_Base {
604
  *
605
  * @since 2.0.0
606
  *
607
- * @return SquareConnect\Model\Location[]
608
- * @throws Framework\SV_WC_API_Exception
609
  */
610
  public function get_locations() {
611
 
@@ -632,7 +626,7 @@ class API extends Framework\SV_WC_API_Base {
632
  *
633
  * @param string $cursor pagination cursor
634
  * @return API\Response
635
- * @throws Framework\SV_WC_API_Exception
636
  */
637
  public function get_customers( $cursor = '' ) {
638
 
@@ -655,7 +649,7 @@ class API extends Framework\SV_WC_API_Base {
655
  * @since 2.0.0
656
  *
657
  * @return Requests\Catalog
658
- * @throws Framework\SV_WC_API_Exception
659
  */
660
  protected function get_catalog_request() {
661
 
@@ -669,7 +663,7 @@ class API extends Framework\SV_WC_API_Base {
669
  * @since 2.0.0
670
  *
671
  * @return Requests\Inventory
672
- * @throws Framework\SV_WC_API_Exception
673
  */
674
  protected function get_inventory_request() {
675
 
@@ -684,7 +678,7 @@ class API extends Framework\SV_WC_API_Base {
684
  *
685
  * @param string $type desired request type
686
  * @return Requests\Catalog|Requests\Inventory
687
- * @throws Framework\SV_WC_API_Exception
688
  */
689
  protected function get_new_request( $type = '' ) {
690
 
@@ -701,7 +695,7 @@ class API extends Framework\SV_WC_API_Base {
701
  break;
702
 
703
  default:
704
- throw new Framework\SV_WC_API_Exception( 'Invalid request type.' );
705
  }
706
 
707
  $this->set_response_handler( $response_handler );
@@ -713,13 +707,13 @@ class API extends Framework\SV_WC_API_Base {
713
  /**
714
  * Performs an API request.
715
  *
716
- * @see Framework\SV_WC_API_Base::perform_request()
717
  *
718
  * @since 2.0.0
719
  *
720
  * @param API\Request $request request object
721
- * @return Framework\SV_WC_API_Response
722
- * @throws Framework\SV_WC_API_Exception
723
  */
724
  protected function perform_request( $request ) {
725
 
@@ -754,7 +748,7 @@ class API extends Framework\SV_WC_API_Base {
754
  // parse & validate response
755
  $response = $this->handle_response( $response );
756
 
757
- } catch ( Framework\SV_WC_API_Exception $e ) {
758
 
759
  // alert other actors that a request has been made
760
  $this->broadcast_request();
@@ -772,14 +766,10 @@ class API extends Framework\SV_WC_API_Base {
772
  * @since 2.0.0
773
  *
774
  * @param array|\WP_Error $response response data
775
- * @throws Framework\SV_WC_API_Exception
776
- * @return Framework\SV_WC_API_Response|object request class instance that implements SV_WC_API_Request
777
  */
778
  protected function handle_response( $response ) {
779
-
780
- // allow child classes to validate response prior to parsing
781
- $this->do_pre_parse_response_validation();
782
-
783
  // parse the response body and tie it to the request
784
  $this->response = $this->get_parsed_response( $this->raw_response_body );
785
 
@@ -801,7 +791,7 @@ class API extends Framework\SV_WC_API_Base {
801
  * @since 2.0.0
802
  *
803
  * @return bool
804
- * @throws Framework\SV_WC_API_Exception
805
  */
806
  protected function do_post_parse_response_validation() {
807
 
@@ -840,7 +830,7 @@ class API extends Framework\SV_WC_API_Base {
840
  }
841
 
842
  // At this point we could not validate the response and assume a failed attempt.
843
- throw new Framework\SV_WC_API_Exception( implode( ' | ', $errors ) );
844
  }
845
 
846
  /**
@@ -851,31 +841,26 @@ class API extends Framework\SV_WC_API_Base {
851
  * @param Object $square_api the square API class instance
852
  * @param string $method the class method to call
853
  * @param array $args the args to send with the method call
854
- * @throws Framework\SV_WC_API_Exception
855
  */
856
  protected function do_square_request( $square_api, $method, $args ) {
857
 
858
  if ( ! is_callable( array( $square_api, $method ) ) ) {
859
- throw new Framework\SV_WC_API_Exception( 'Invalid API method' );
860
  }
861
 
862
- try {
 
863
 
864
- // perform the request
865
- $response = call_user_func_array( array( $square_api, $method ), $args );
 
866
 
867
- if ( is_array( $response ) && $this->request->get_with_http_info() ) {
868
- $this->response_code = isset( $response[1] ) ? (int) $response[1] : 400;
869
- $this->response_headers = isset( $response[2] ) ? (array) $response[2] : array();
870
- $this->raw_response_body = isset( $response[0] ) ? $response[0] : array();
871
  } else {
872
- $this->raw_response_body = $response;
873
  }
874
- } catch ( SquareConnect\ApiException $exception ) {
875
-
876
- $this->response_code = $exception->getCode();
877
- $this->response_headers = $exception->getResponseHeaders();
878
- $this->raw_response_body = $exception->getResponseBody();
879
  }
880
  }
881
 
23
 
24
  namespace WooCommerce\Square;
25
 
26
+ use WooCommerce\Square\Framework\Api\Base;
 
27
  use WooCommerce\Square\API\Requests;
28
  use WooCommerce\Square\API\Responses;
29
+ use Square\SquareClient;
30
+ use Square\Environment;
31
 
32
  defined( 'ABSPATH' ) || exit;
33
 
36
  *
37
  * @since 2.0.0
38
  */
39
+ class API extends Base {
40
 
41
 
42
  /** catalog request type */
46
  const REQUEST_TYPE_INVENTORY = 'inventory';
47
 
48
 
49
+ /** @var \Square\SquareClient Square API client instance */
50
  protected $client;
51
 
52
 
59
  * @param bool $is_sandbox If sandbox access is desired
60
  */
61
  public function __construct( $access_token, $is_sandbox = null ) {
62
+ $this->client = new SquareClient( [
63
+ 'accessToken' => $access_token,
64
+ 'environment' => $is_sandbox ? Environment::SANDBOX : Environment::PRODUCTION,
65
+ ] );
 
 
 
 
 
66
  }
67
 
68
 
76
  *
77
  * @param string[] $object_ids array of square catalog object IDs
78
  * @return Responses\Catalog
79
+ * @throws \Exception
80
  */
81
  public function batch_delete_catalog_objects( array $object_ids ) {
82
 
95
  * @param string[] $object_ids array of square catalog object IDs
96
  * @param bool $include_related_objects whether or not to include related objects in the response
97
  * @return Responses\Catalog
98
+ * @throws \Exception
99
  */
100
  public function batch_retrieve_catalog_objects( array $object_ids, $include_related_objects = false ) {
101
 
114
  * @param string $idempotency_key a UUID for this request
115
  * @param array $batches an array of batches to upsert
116
  * @return Responses\Catalog
117
+ * @throws \Exception
118
  */
119
  public function batch_upsert_catalog_objects( $idempotency_key, array $batches ) {
120
 
130
  *
131
  * @since 2.0.0
132
  * @return Responses\Catalog
133
+ * @throws \Exception
134
  */
135
  public function catalog_info() {
136
 
148
  *
149
  * @param string $object_id Square catalog object ID
150
  * @return Responses\Catalog
151
+ * @throws \Exception
152
  */
153
  public function delete_catalog_object( $object_id ) {
154
 
167
  * @param string $cursor the cursor to list from
168
  * @param string[] $types the item types to filter by
169
  * @return Responses\Catalog
170
+ * @throws \Exception
171
  */
172
  public function list_catalog( $cursor = '', $types = array() ) {
173
 
186
  * @param string $object_id the Square catalog object ID
187
  * @param bool $include_related_objects whether or not to include related objects (such as categories)
188
  * @return Responses\Catalog
189
+ * @throws \Exception
190
  */
191
  public function retrieve_catalog_object( $object_id, $include_related_objects = false ) {
192
 
204
  *
205
  * @param array $args see Catalog::set_search_catalog_objects_data() for list of args
206
  * @return Responses\Catalog
207
+ * @throws \Exception
208
  */
209
  public function search_catalog_objects( $args = array() ) {
210
 
224
  * @param string[] $modifier_lists_to_enable (optional) modifier list IDs to enable
225
  * @param string[] $modifier_lists_to_disable (optional) modifier list IDs to disable
226
  * @return Responses\Catalog
227
+ * @throws \Exception
228
  */
229
  public function update_item_modifier_lists( array $item_ids, array $modifier_lists_to_enable = array(), array $modifier_lists_to_disable = array() ) {
230
 
244
  * @param string[] $taxes_to_enable (optional) tax IDs to enable
245
  * @param string[] $taxes_to_disable (optional) tax IDs to disable
246
  * @return Responses\Catalog
247
+ * @throws \Exception
248
  */
249
  public function update_item_taxes( array $item_ids, array $taxes_to_enable = array(), array $taxes_to_disable = array() ) {
250
 
261
  * @since 2.0.0
262
  *
263
  * @param string $idempotency_key UUID for this request
264
+ * @param \Square\Models\CatalogObject $object the object to upsert
265
  * @return Responses\Catalog
266
+ * @throws \Exception
267
  */
268
  public function upsert_catalog_object( $idempotency_key, $object ) {
269
 
285
  * @param string $square_item_id
286
  * @param string $caption optional image caption
287
  * @return string
288
+ * @throws \Exception
289
  */
290
  public function create_image( $image_path, $square_item_id = '', $caption = '' ) {
291
 
292
  if ( ! is_readable( $image_path ) ) {
293
+ throw new \Exception( 'Image file is not readable' );
294
  }
295
 
296
  $image = file_get_contents( $image_path );
331
  $body .= $image . "\r\n";
332
  $body .= '--boundary--';
333
 
334
+ $url = $this->client->getBaseUri() . '/v2/catalog/images';
335
 
336
  $response = wp_remote_post(
337
  $url,
342
  );
343
 
344
  if ( is_wp_error( $response ) ) {
345
+ throw new \Exception( $response->get_error_message() );
346
  }
347
 
348
  $body = wp_remote_retrieve_body( $response );
349
  $body = json_decode( $body, true );
350
 
351
  if ( ! is_array( $body ) ) {
352
+ throw new \Exception( 'Response was malformed' );
353
  }
354
 
355
  if ( ! empty( $body['errors'] ) || empty( $body['image']['id'] ) ) {
360
  $message = 'Unknown error';
361
  }
362
 
363
+ throw new \Exception( $message );
364
  }
365
 
366
  return $body['image']['id'];
378
  * @param string $square_id Square object ID
379
  * @param int $amount amount of inventory to add
380
  * @return Responses\Inventory
381
+ * @throws \Exception
382
  */
383
  public function add_inventory_from_refund( $square_id, $amount ) {
384
 
395
  * @param int $amount amount of inventory to add
396
  * @param string $from_state the API state the inventory is coming from
397
  * @return Responses\Inventory
398
+ * @throws \Exception
399
  */
400
  public function add_inventory( $square_id, $amount, $from_state = 'NONE' ) {
401
 
411
  * @param string $square_id Square object ID
412
  * @param int $amount amount of inventory to remove
413
  * @return Responses\Inventory
414
+ * @throws \Exception
415
  */
416
  public function remove_inventory( $square_id, $amount ) {
417
 
429
  * @param string $from_state the API state the inventory is coming from
430
  * @param string $to_state the API state the inventory is changing to
431
  * @return Responses\Inventory
432
+ * @throws \Exception
433
  */
434
  protected function adjust_inventory( $square_id, $amount, $from_state, $to_state ) {
435
 
436
  $date = new \DateTime();
437
 
438
+ $change = new \Square\Models\InventoryChange();
439
  $change->setType( 'ADJUSTMENT' );
440
+
441
+ $inventory_adjustment = new \Square\Models\InventoryAdjustment();
442
+ $inventory_adjustment->setCatalogObjectId( $square_id );
443
+ $inventory_adjustment->setLocationId( $this->get_plugin()->get_settings_handler()->get_location_id() );
444
+ $inventory_adjustment->setQuantity( (string) absint( $amount ) );
445
+ $inventory_adjustment->setFromState( $from_state );
446
+ $inventory_adjustment->setToState( $to_state );
447
+ $inventory_adjustment->setOccurredAt( $date->format( DATE_ATOM ) );
448
+
449
+ $change->setAdjustment( $inventory_adjustment );
 
 
450
 
451
  return $this->batch_change_inventory(
452
  uniqid( '', false ),
463
  * @since 2.0.0
464
  *
465
  * @param string $idempotency_key UUID for this request
466
+ * @param \Square\Models\InventoryChange[] $changes array of Inventory Changes
467
  * @param bool $ignore_unchanged_counts whether the current physical count should be ignored if the quantity is unchanged since the last physical count
468
  * @return Responses\Inventory
469
+ * @throws \Exception
470
  */
471
  public function batch_change_inventory( $idempotency_key, $changes, $ignore_unchanged_counts = true ) {
472
 
485
  * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_changes_data() for accepted arguments
486
  *
487
  * @return Responses\Inventory
488
+ * @throws \Exception
489
  */
490
  public function batch_retrieve_inventory_changes( array $args = array() ) {
491
 
504
  * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_counts_data() for accepted arguments
505
  *
506
  * @return Responses\Inventory
507
+ * @throws \Exception
508
  */
509
  public function batch_retrieve_inventory_counts( array $args = array() ) {
510
 
523
  * @param string $adjustment_id the InventoryAdjustment ID to retrieve
524
  *
525
  * @return Responses\Inventory
526
+ * @throws \Exception
527
  */
528
  public function retrieve_inventory_adjustment( $adjustment_id ) {
529
 
542
  * @param string $catalog_object_id the CatalogObject ID to retrieve
543
  *
544
  * @return Responses\Inventory
545
+ * @throws \Exception
546
  */
547
  public function retrieve_inventory_changes( $catalog_object_id ) {
548
 
560
  *
561
  * @param string $catalog_object_id the CatalogObject ID to retrieve
562
  * @return Responses\Inventory
563
+ * @throws \Exception
564
  */
565
  public function retrieve_inventory_count( $catalog_object_id ) {
566
 
567
  $request = $this->get_inventory_request();
568
+ $request->set_retrieve_inventory_count_data( $catalog_object_id, $this->get_plugin()->get_settings_handler()->get_location_id() );
569
 
570
  return $this->perform_request( $request );
571
  }
579
  * @param string $physical_count_id the InventoryPhysicalCount ID to retrieve
580
  *
581
  * @return Responses\Inventory
582
+ * @throws \Exception
583
  */
584
  public function retrieve_inventory_physical_count( $physical_count_id ) {
585
 
598
  *
599
  * @since 2.0.0
600
  *
601
+ * @return \Square\Models\Location[]
602
+ * @throws \Exception
603
  */
604
  public function get_locations() {
605
 
626
  *
627
  * @param string $cursor pagination cursor
628
  * @return API\Response
629
+ * @throws \Exception
630
  */
631
  public function get_customers( $cursor = '' ) {
632
 
649
  * @since 2.0.0
650
  *
651
  * @return Requests\Catalog
652
+ * @throws \Exception
653
  */
654
  protected function get_catalog_request() {
655
 
663
  * @since 2.0.0
664
  *
665
  * @return Requests\Inventory
666
+ * @throws \Exception
667
  */
668
  protected function get_inventory_request() {
669
 
678
  *
679
  * @param string $type desired request type
680
  * @return Requests\Catalog|Requests\Inventory
681
+ * @throws \Exception
682
  */
683
  protected function get_new_request( $type = '' ) {
684
 
695
  break;
696
 
697
  default:
698
+ throw new \Exception( 'Invalid request type.' );
699
  }
700
 
701
  $this->set_response_handler( $response_handler );
707
  /**
708
  * Performs an API request.
709
  *
710
+ * @see Base::perform_request()
711
  *
712
  * @since 2.0.0
713
  *
714
  * @param API\Request $request request object
715
+ * @return API_Response
716
+ * @throws \Exception
717
  */
718
  protected function perform_request( $request ) {
719
 
748
  // parse & validate response
749
  $response = $this->handle_response( $response );
750
 
751
+ } catch ( \Exception $e ) {
752
 
753
  // alert other actors that a request has been made
754
  $this->broadcast_request();
766
  * @since 2.0.0
767
  *
768
  * @param array|\WP_Error $response response data
769
+ * @throws \Exception
770
+ * @return API_Response|object request class instance that implements API_Request
771
  */
772
  protected function handle_response( $response ) {
 
 
 
 
773
  // parse the response body and tie it to the request
774
  $this->response = $this->get_parsed_response( $this->raw_response_body );
775
 
791
  * @since 2.0.0
792
  *
793
  * @return bool
794
+ * @throws \Exception
795
  */
796
  protected function do_post_parse_response_validation() {
797
 
830
  }
831
 
832
  // At this point we could not validate the response and assume a failed attempt.
833
+ throw new \Exception( implode( ' | ', $errors ) );
834
  }
835
 
836
  /**
841
  * @param Object $square_api the square API class instance
842
  * @param string $method the class method to call
843
  * @param array $args the args to send with the method call
844
+ * @throws \Exception
845
  */
846
  protected function do_square_request( $square_api, $method, $args ) {
847
 
848
  if ( ! is_callable( array( $square_api, $method ) ) ) {
849
+ throw new \Exception( 'Invalid API method' );
850
  }
851
 
852
+ // perform the request
853
+ $response = call_user_func_array( array( $square_api, $method ), $args );
854
 
855
+ if ( $response instanceof \Square\Http\ApiResponse ) {
856
+ $this->response_code = $response->getStatusCode();
857
+ $this->response_headers = $response->getHeaders();
858
 
859
+ if ( $response->isSuccess() ) {
860
+ $this->raw_response_body = $response->getResult();
 
 
861
  } else {
862
+ $this->raw_response_body = $response->getErrors();
863
  }
 
 
 
 
 
864
  }
865
  }
866
 
includes/API/Request.php CHANGED
@@ -23,8 +23,8 @@
23
 
24
  namespace WooCommerce\Square\API;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
  use SquareConnect\Configuration;
 
28
 
29
  defined( 'ABSPATH' ) || exit;
30
 
@@ -33,7 +33,7 @@ defined( 'ABSPATH' ) || exit;
33
  *
34
  * @since 2.0.0
35
  */
36
- class Request implements Framework\SV_WC_API_Request {
37
 
38
 
39
  /** @var Configuration the configuration object */
@@ -76,10 +76,7 @@ class Request implements Framework\SV_WC_API_Request {
76
  * @return string
77
  */
78
  public function get_square_api_method() {
79
-
80
- $method = $this->square_api_method;
81
-
82
- return $this->with_http_info ? $method . 'WithHttpInfo' : $method;
83
  }
84
 
85
 
23
 
24
  namespace WooCommerce\Square\API;
25
 
 
26
  use SquareConnect\Configuration;
27
+ use \WooCommerce\Square\Framework\Api\API_Request;
28
 
29
  defined( 'ABSPATH' ) || exit;
30
 
33
  *
34
  * @since 2.0.0
35
  */
36
+ class Request implements API_Request {
37
 
38
 
39
  /** @var Configuration the configuration object */
76
  * @return string
77
  */
78
  public function get_square_api_method() {
79
+ return $this->square_api_method;
 
 
 
80
  }
81
 
82
 
includes/API/Requests/Catalog.php CHANGED
@@ -23,9 +23,6 @@
23
 
24
  namespace WooCommerce\Square\API\Requests;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect\Model as SquareModel;
28
- use SquareConnect\Api\CatalogApi;
29
  use WooCommerce\Square\API\Request;
30
 
31
  defined( 'ABSPATH' ) || exit;
@@ -43,11 +40,10 @@ class Catalog extends Request {
43
  *
44
  * @since 2.0.0
45
  *
46
- * @param \SquareConnect\ApiClient $api_client the API client
47
  */
48
  public function __construct( $api_client ) {
49
-
50
- $this->square_api = new CatalogApi( $api_client );
51
  }
52
 
53
 
@@ -55,7 +51,7 @@ class Catalog extends Request {
55
  * Sets the data for a batchDeleteCatalogObjects request.
56
  *
57
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchdeletecatalogobjects
58
- * @see \SquareConnect\Api\CatalogApi::batchDeleteCatalogObjects()
59
  *
60
  * @since 2.0.0
61
  *
@@ -64,7 +60,9 @@ class Catalog extends Request {
64
  public function set_batch_delete_catalog_objects_data( array $object_ids ) {
65
 
66
  $this->square_api_method = 'batchDeleteCatalogObjects';
67
- $this->square_api_args = array( new SquareModel\BatchDeleteCatalogObjectsRequest( array( 'object_ids' => $object_ids ) ) );
 
 
68
  }
69
 
70
 
@@ -72,7 +70,7 @@ class Catalog extends Request {
72
  * Sets the data for a batchRetrieveCatalogObjects request.
73
  *
74
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchretrievecatalogobjects
75
- * @see \SquareConnect\Api\CatalogApi::batchRetrieveCatalogObjects()
76
  *
77
  * @since 2.0.0
78
  *
@@ -82,14 +80,10 @@ class Catalog extends Request {
82
  public function set_batch_retrieve_catalog_objects_data( array $object_ids, $include_related_objects = false ) {
83
 
84
  $this->square_api_method = 'batchRetrieveCatalogObjects';
85
- $this->square_api_args = array(
86
- new SquareModel\BatchRetrieveCatalogObjectsRequest(
87
- array(
88
- 'object_ids' => $object_ids,
89
- 'include_related_objects' => (bool) $include_related_objects,
90
- )
91
- ),
92
- );
93
  }
94
 
95
 
@@ -97,22 +91,20 @@ class Catalog extends Request {
97
  * Sets the data for a batchUpsertCatalogObjects request.
98
  *
99
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchupsertcatalogobjects
100
- * @see \SquareConnect\Api\CatalogApi::batchUpsertCatalogObjects()
101
  *
102
  * @since 2.0.0
103
  *
104
  * @param string $idempotency_key the UUID for this request
105
- * @param SquareModel\CatalogObjectBatch[] $batches array of catalog object batches
106
  */
107
  public function set_batch_upsert_catalog_objects_data( $idempotency_key, array $batches ) {
108
 
109
  $this->square_api_method = 'batchUpsertCatalogObjects';
110
  $this->square_api_args = array(
111
- new SquareModel\BatchUpsertCatalogObjectsRequest(
112
- array(
113
- 'idempotency_key' => $idempotency_key,
114
- 'batches' => $batches,
115
- )
116
  ),
117
  );
118
  }
@@ -122,7 +114,7 @@ class Catalog extends Request {
122
  * Sets the data for a catalogInfo request.
123
  *
124
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-cataloginfo
125
- * @see \SquareConnect\Api\CatalogApi::catalogInfo()
126
  *
127
  * @since 2.0.0
128
  *
@@ -139,7 +131,7 @@ class Catalog extends Request {
139
  * Sets the data for a deleteCatalogObject request.
140
  *
141
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-deletecatalogobject
142
- * @see \SquareConnect\Api\CatalogApi::deleteCatalogObject()
143
  *
144
  * @since 2.0.0
145
  *
@@ -156,7 +148,7 @@ class Catalog extends Request {
156
  * Sets the data for a listCatalog request.
157
  *
158
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-listcatalog
159
- * @see \SquareConnect\Api\CatalogApi::listCatalog()
160
  *
161
  * @since 2.0.0
162
  *
@@ -177,7 +169,7 @@ class Catalog extends Request {
177
  * Sets the data for a retrieveCatalogObject request.
178
  *
179
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-retrievecatalogobject
180
- * @see \SquareConnect\Api\CatalogApi::retrieveCatalogObject()
181
  *
182
  * @since 2.0.0
183
  *
@@ -195,7 +187,7 @@ class Catalog extends Request {
195
  * Sets the data for a searchCatalogObjects request.
196
  *
197
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-searchcatalogobjects
198
- * @see \SquareConnect\Api\CatalogApi::searchCatalogObjects()
199
  *
200
  * @since 2.0.0
201
  *
@@ -221,8 +213,17 @@ class Catalog extends Request {
221
  // apply defaults and remove any keys that aren't recognized
222
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
223
 
 
 
 
 
 
 
 
 
 
224
  $this->square_api_method = 'searchCatalogObjects';
225
- $this->square_api_args = array( new SquareModel\SearchCatalogObjectsRequest( $args ) );
226
  }
227
 
228
 
@@ -230,7 +231,7 @@ class Catalog extends Request {
230
  * Sets the data for a updateItemModifierLists request.
231
  *
232
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-updateitemmodifierlists
233
- * @see \SquareConnect\Api\CatalogApi::updateItemModifierLists()
234
  *
235
  * @since 2.0.0
236
  *
@@ -241,15 +242,11 @@ class Catalog extends Request {
241
  public function set_update_item_modifier_lists_data( array $item_ids, array $modifier_lists_to_enable = array(), array $modifier_lists_to_disable = array() ) {
242
 
243
  $this->square_api_method = 'updateItemModifierLists';
244
- $this->square_api_args = array(
245
- new SquareModel\UpdateItemModifierListsRequest(
246
- array(
247
- 'item_ids' => $item_ids,
248
- 'modifier_lists_to_enable' => $modifier_lists_to_enable,
249
- 'modifier_lists_to_disable' => $modifier_lists_to_disable,
250
- )
251
- ),
252
- );
253
  }
254
 
255
 
@@ -257,7 +254,7 @@ class Catalog extends Request {
257
  * Sets the data for an updateItemTaxes request.
258
  *
259
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-updateitemtaxes
260
- * @see \SquareConnect\Api\CatalogApi::updateItemTaxes()
261
  *
262
  * @since 2.0.0
263
  *
@@ -268,15 +265,10 @@ class Catalog extends Request {
268
  public function set_update_item_taxes_data( array $item_ids, array $taxes_to_enable = array(), array $taxes_to_disable = array() ) {
269
 
270
  $this->square_api_method = 'updateItemTaxes';
271
- $this->square_api_args = array(
272
- new SquareModel\UpdateItemTaxesRequest(
273
- array(
274
- 'item_ids' => $item_ids,
275
- 'taxes_to_enable' => $taxes_to_enable,
276
- 'taxes_to_disable' => $taxes_to_disable,
277
- )
278
- ),
279
- );
280
  }
281
 
282
 
@@ -284,22 +276,20 @@ class Catalog extends Request {
284
  * Sets the data for an upsertCatalogObject request.
285
  *
286
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-upsertcatalogobject
287
- * @see \SquareConnect\Api\CatalogApi::upsertCatalogObject()
288
  *
289
  * @since 2.0.0
290
  *
291
  * @param string $idempotency_key a UUID for this request
292
- * @param SquareModel\CatalogObject $object the object to update
293
  */
294
  public function set_upsert_catalog_object_data( $idempotency_key, $object ) {
295
 
296
  $this->square_api_method = 'upsertCatalogObject';
297
  $this->square_api_args = array(
298
- new SquareModel\UpsertCatalogObjectRequest(
299
- array(
300
- 'idempotency_key' => $idempotency_key,
301
- 'object' => $object,
302
- )
303
  ),
304
  );
305
  }
23
 
24
  namespace WooCommerce\Square\API\Requests;
25
 
 
 
 
26
  use WooCommerce\Square\API\Request;
27
 
28
  defined( 'ABSPATH' ) || exit;
40
  *
41
  * @since 2.0.0
42
  *
43
+ * @param \Square\SquareClient $api_client the API client
44
  */
45
  public function __construct( $api_client ) {
46
+ $this->square_api = $api_client->getCatalogApi();
 
47
  }
48
 
49
 
51
  * Sets the data for a batchDeleteCatalogObjects request.
52
  *
53
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchdeletecatalogobjects
54
+ * @see \Square\Apis\CatalogApi::batchDeleteCatalogObjects()
55
  *
56
  * @since 2.0.0
57
  *
60
  public function set_batch_delete_catalog_objects_data( array $object_ids ) {
61
 
62
  $this->square_api_method = 'batchDeleteCatalogObjects';
63
+ $body = new \Square\Models\BatchDeleteCatalogObjectsRequest();
64
+ $body->setObjectIds( $object_ids );
65
+ $this->square_api_args = array( $body );
66
  }
67
 
68
 
70
  * Sets the data for a batchRetrieveCatalogObjects request.
71
  *
72
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchretrievecatalogobjects
73
+ * @see \Square\Apis\CatalogApi::batchRetrieveCatalogObjects()
74
  *
75
  * @since 2.0.0
76
  *
80
  public function set_batch_retrieve_catalog_objects_data( array $object_ids, $include_related_objects = false ) {
81
 
82
  $this->square_api_method = 'batchRetrieveCatalogObjects';
83
+ $body = new \Square\Models\BatchRetrieveCatalogObjectsRequest( $object_ids );
84
+ $body->setIncludeRelatedObjects( (bool) $include_related_objects );
85
+
86
+ $this->square_api_args = array( $body );
 
 
 
 
87
  }
88
 
89
 
91
  * Sets the data for a batchUpsertCatalogObjects request.
92
  *
93
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-batchupsertcatalogobjects
94
+ * @see \Square\Apis\CatalogApi::batchUpsertCatalogObjects()
95
  *
96
  * @since 2.0.0
97
  *
98
  * @param string $idempotency_key the UUID for this request
99
+ * @param \Square\Models\CatalogObjectBatch[] $batches array of catalog object batches
100
  */
101
  public function set_batch_upsert_catalog_objects_data( $idempotency_key, array $batches ) {
102
 
103
  $this->square_api_method = 'batchUpsertCatalogObjects';
104
  $this->square_api_args = array(
105
+ new \Square\Models\BatchUpsertCatalogObjectsRequest(
106
+ $idempotency_key,
107
+ $batches
 
 
108
  ),
109
  );
110
  }
114
  * Sets the data for a catalogInfo request.
115
  *
116
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-cataloginfo
117
+ * @see \Square\Apis\CatalogApi::catalogInfo()
118
  *
119
  * @since 2.0.0
120
  *
131
  * Sets the data for a deleteCatalogObject request.
132
  *
133
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-deletecatalogobject
134
+ * @see \Square\Apis\CatalogApi::deleteCatalogObject()
135
  *
136
  * @since 2.0.0
137
  *
148
  * Sets the data for a listCatalog request.
149
  *
150
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-listcatalog
151
+ * @see \Square\Apis\CatalogApi::listCatalog()
152
  *
153
  * @since 2.0.0
154
  *
169
  * Sets the data for a retrieveCatalogObject request.
170
  *
171
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-retrievecatalogobject
172
+ * @see \Square\Apis\CatalogApi::retrieveCatalogObject()
173
  *
174
  * @since 2.0.0
175
  *
187
  * Sets the data for a searchCatalogObjects request.
188
  *
189
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-searchcatalogobjects
190
+ * @see \Square\Apis\CatalogApi::searchCatalogObjects()
191
  *
192
  * @since 2.0.0
193
  *
213
  // apply defaults and remove any keys that aren't recognized
214
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
215
 
216
+ $body = new \Square\Models\SearchCatalogObjectsRequest();
217
+ $body->setCursor( $args['cursor'] );
218
+ $body->setObjectTypes( $args['object_types'] );
219
+ $body->setIncludeDeletedObjects( $args['include_deleted_objects'] );
220
+ $body->setIncludeRelatedObjects( $args['include_related_objects'] );
221
+ $body->setBeginTime( $args['begin_time'] );
222
+ $body->setQuery( $args['query'] );
223
+ $body->setLimit( $args['limit'] );
224
+
225
  $this->square_api_method = 'searchCatalogObjects';
226
+ $this->square_api_args = array( $body );
227
  }
228
 
229
 
231
  * Sets the data for a updateItemModifierLists request.
232
  *
233
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-updateitemmodifierlists
234
+ * @see \Square\Apis\CatalogApi::updateItemModifierLists()
235
  *
236
  * @since 2.0.0
237
  *
242
  public function set_update_item_modifier_lists_data( array $item_ids, array $modifier_lists_to_enable = array(), array $modifier_lists_to_disable = array() ) {
243
 
244
  $this->square_api_method = 'updateItemModifierLists';
245
+ $body = new \Square\Models\UpdateItemModifierListsRequest( $item_ids );
246
+ $body->setModifierListsToEnable( $modifier_lists_to_enable );
247
+ $body->setModifierListsToDisable( $modifier_lists_to_disable );
248
+
249
+ $this->square_api_args = array( $body );
 
 
 
 
250
  }
251
 
252
 
254
  * Sets the data for an updateItemTaxes request.
255
  *
256
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-updateitemtaxes
257
+ * @see \Square\Apis\CatalogApi::updateItemTaxes()
258
  *
259
  * @since 2.0.0
260
  *
265
  public function set_update_item_taxes_data( array $item_ids, array $taxes_to_enable = array(), array $taxes_to_disable = array() ) {
266
 
267
  $this->square_api_method = 'updateItemTaxes';
268
+ $body = new \Square\Models\UpdateItemTaxesRequest( $item_ids );
269
+ $body->setTaxesToEnable( $taxes_to_enable );
270
+ $body->setTaxesToDisable( $taxes_to_disable );
271
+ $this->square_api_args = array( $body );
 
 
 
 
 
272
  }
273
 
274
 
276
  * Sets the data for an upsertCatalogObject request.
277
  *
278
  * @see https://docs.connect.squareup.com/api/connect/v2#endpoint-catalog-upsertcatalogobject
279
+ * @see \Square\Apis\CatalogApi::upsertCatalogObject()
280
  *
281
  * @since 2.0.0
282
  *
283
  * @param string $idempotency_key a UUID for this request
284
+ * @param \Square\Models\CatalogObject $object the object to update
285
  */
286
  public function set_upsert_catalog_object_data( $idempotency_key, $object ) {
287
 
288
  $this->square_api_method = 'upsertCatalogObject';
289
  $this->square_api_args = array(
290
+ new \Square\Models\UpsertCatalogObjectRequest(
291
+ $idempotency_key,
292
+ $object
 
 
293
  ),
294
  );
295
  }
includes/API/Requests/Customers.php CHANGED
@@ -25,7 +25,6 @@ namespace WooCommerce\Square\API\Requests;
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SquareConnect\Api\CustomersApi;
29
  use WooCommerce\Square\API;
30
 
31
  /**
@@ -41,11 +40,10 @@ class Customers extends API\Request {
41
  *
42
  * @since 2.0.0
43
  *
44
- * @param \SquareConnect\ApiClient $api_client the API client
45
  */
46
  public function __construct( $api_client ) {
47
-
48
- $this->square_api = new CustomersApi( $api_client );
49
  }
50
 
51
 
@@ -76,7 +74,7 @@ class Customers extends API\Request {
76
  $this->square_api_method = 'listCustomers';
77
 
78
  if ( $cursor ) {
79
- $this->square_api_args = array( 'cursor' => $cursor );
80
  }
81
  }
82
 
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
 
28
  use WooCommerce\Square\API;
29
 
30
  /**
40
  *
41
  * @since 2.0.0
42
  *
43
+ * @param \Square\SquareClient $api_client the API client
44
  */
45
  public function __construct( $api_client ) {
46
+ $this->square_api = $api_client->getCustomersApi();
 
47
  }
48
 
49
 
74
  $this->square_api_method = 'listCustomers';
75
 
76
  if ( $cursor ) {
77
+ $this->square_api_args = array( $cursor );
78
  }
79
  }
80
 
includes/API/Requests/Inventory.php CHANGED
@@ -23,9 +23,6 @@
23
 
24
  namespace WooCommerce\Square\API\Requests;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect\Model as SquareModel;
28
- use SquareConnect\Api\InventoryApi;
29
  use WooCommerce\Square\API\Request;
30
 
31
  defined( 'ABSPATH' ) || exit;
@@ -43,11 +40,10 @@ class Inventory extends Request {
43
  *
44
  * @since 2.0.0
45
  *
46
- * @param \SquareConnect\ApiClient $api_client the API client
47
  */
48
  public function __construct( $api_client ) {
49
-
50
- $this->square_api = new InventoryApi( $api_client );
51
  }
52
 
53
 
@@ -60,21 +56,16 @@ class Inventory extends Request {
60
  * @since 2.0.0
61
  *
62
  * @param string $idempotency_key a UUID for this request
63
- * @param SquareModel\InventoryChange[] $changes array of inventory changes to be made
64
  * @param bool $ignore_unchanged_counts whether the current physical count should be ignored if the quantity is unchanged since the last physical count
65
  */
66
  public function set_batch_change_inventory_data( $idempotency_key, $changes, $ignore_unchanged_counts = true ) {
67
 
 
 
 
68
  $this->square_api_method = 'batchChangeInventory';
69
- $this->square_api_args = array(
70
- new SquareModel\BatchChangeInventoryRequest(
71
- array(
72
- 'idempotency_key' => $idempotency_key,
73
- 'changes' => $changes,
74
- 'ignore_unchanged_counts' => (bool) $ignore_unchanged_counts,
75
- )
76
- ),
77
- );
78
  }
79
 
80
 
@@ -109,9 +100,17 @@ class Inventory extends Request {
109
 
110
  // apply defaults and remove any keys that aren't recognized
111
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
 
 
 
 
 
 
 
 
112
 
113
  $this->square_api_method = 'batchRetrieveInventoryChanges';
114
- $this->square_api_args = array( new SquareModel\BatchRetrieveInventoryChangesRequest( $args ) );
115
  }
116
 
117
 
@@ -140,9 +139,13 @@ class Inventory extends Request {
140
 
141
  // apply defaults and remove any keys that aren't recognized
142
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
143
-
 
 
 
 
144
  $this->square_api_method = 'batchRetrieveInventoryCounts';
145
- $this->square_api_args = array( new SquareModel\BatchRetrieveInventoryCountsRequest( $args ) );
146
  }
147
 
148
 
@@ -175,8 +178,15 @@ class Inventory extends Request {
175
  */
176
  public function set_retrieve_inventory_changes_data( $catalog_object_id ) {
177
 
178
- $this->square_api_method = 'retrieveInventoryChanges';
179
- $this->square_api_args = array( $catalog_object_id );
 
 
 
 
 
 
 
180
  }
181
 
182
 
@@ -189,9 +199,9 @@ class Inventory extends Request {
189
  * @since 2.0.0
190
  *
191
  * @param string $catalog_object_id the CatalogObject ID to retrieve
192
- * @param string[] $location_ids location IDs
193
  */
194
- public function set_retrieve_inventory_count_data( $catalog_object_id, array $location_ids = array() ) {
195
 
196
  $this->square_api_method = 'retrieveInventoryCount';
197
  $this->square_api_args = array( $catalog_object_id, $location_ids );
23
 
24
  namespace WooCommerce\Square\API\Requests;
25
 
 
 
 
26
  use WooCommerce\Square\API\Request;
27
 
28
  defined( 'ABSPATH' ) || exit;
40
  *
41
  * @since 2.0.0
42
  *
43
+ * @param \Square\SquareClient $api_client the API client
44
  */
45
  public function __construct( $api_client ) {
46
+ $this->square_api = $api_client->getInventoryApi();
 
47
  }
48
 
49
 
56
  * @since 2.0.0
57
  *
58
  * @param string $idempotency_key a UUID for this request
59
+ * @param \Square\Models\InventoryChange[] $changes array of inventory changes to be made
60
  * @param bool $ignore_unchanged_counts whether the current physical count should be ignored if the quantity is unchanged since the last physical count
61
  */
62
  public function set_batch_change_inventory_data( $idempotency_key, $changes, $ignore_unchanged_counts = true ) {
63
 
64
+ $body = new \Square\Models\BatchChangeInventoryRequest( $idempotency_key );
65
+ $body->setChanges( $changes );
66
+ $body->setIgnoreUnchangedCounts( (bool) $ignore_unchanged_counts );
67
  $this->square_api_method = 'batchChangeInventory';
68
+ $this->square_api_args = array( $body );
 
 
 
 
 
 
 
 
69
  }
70
 
71
 
100
 
101
  // apply defaults and remove any keys that aren't recognized
102
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
103
+ $body = new \Square\Models\BatchRetrieveInventoryChangesRequest();
104
+ $body->setCatalogObjectIds( $args['catalog_object_ids'] );
105
+ $body->setLocationIds( $args['location_ids'] );
106
+ $body->setTypes( $args['types'] );
107
+ $body->setStates( $args['states'] );
108
+ $body->setUpdatedAfter( $args['updated_after'] );
109
+ $body->setUpdatedBefore( $args['updated_before'] );
110
+ $body->setCursor( $args['cursor'] );
111
 
112
  $this->square_api_method = 'batchRetrieveInventoryChanges';
113
+ $this->square_api_args = array( $body );
114
  }
115
 
116
 
139
 
140
  // apply defaults and remove any keys that aren't recognized
141
  $args = array_intersect_key( wp_parse_args( $args, $defaults ), $defaults );
142
+ $body = new \Square\Models\BatchRetrieveInventoryCountsRequest();
143
+ $body->setCatalogObjectIds( $args['catalog_object_ids'] );
144
+ $body->setLocationIds( $args['location_ids'] );
145
+ $body->setUpdatedAfter( $args['updated_after'] );
146
+ $body->setCursor( $args['cursor'] );
147
  $this->square_api_method = 'batchRetrieveInventoryCounts';
148
+ $this->square_api_args = array( $body );
149
  }
150
 
151
 
178
  */
179
  public function set_retrieve_inventory_changes_data( $catalog_object_id ) {
180
 
181
+ /**
182
+ * `retrieveInventoryChanges` is deprecated.
183
+ * Using `batchRetrieveInventoryChanges` instead.
184
+ */
185
+ $this->square_api_method = 'batchRetrieveInventoryChanges';
186
+ $body = new \Square\Models\BatchRetrieveInventoryChangesRequest();
187
+ $body->setCatalogObjectIds( [ $catalog_object_id ] );
188
+
189
+ $this->square_api_args = array( $body );
190
  }
191
 
192
 
199
  * @since 2.0.0
200
  *
201
  * @param string $catalog_object_id the CatalogObject ID to retrieve
202
+ * @param string $location_ids location IDs
203
  */
204
+ public function set_retrieve_inventory_count_data( $catalog_object_id, string $location_ids = '' ) {
205
 
206
  $this->square_api_method = 'retrieveInventoryCount';
207
  $this->square_api_args = array( $catalog_object_id, $location_ids );
includes/API/Requests/Locations.php CHANGED
@@ -22,10 +22,6 @@
22
  */
23
 
24
  namespace WooCommerce\Square\API\Requests;
25
-
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect\Model as SquareModel;
28
- use SquareConnect\Api\LocationsApi;
29
  use WooCommerce\Square\API\Request;
30
 
31
  defined( 'ABSPATH' ) || exit;
@@ -43,11 +39,10 @@ class Locations extends Request {
43
  *
44
  * @since 2.0.0
45
  *
46
- * @param \SquareConnect\ApiClient $api_client the API client
47
  */
48
  public function __construct( $api_client ) {
49
-
50
- $this->square_api = new LocationsApi( $api_client );
51
  }
52
 
53
 
22
  */
23
 
24
  namespace WooCommerce\Square\API\Requests;
 
 
 
 
25
  use WooCommerce\Square\API\Request;
26
 
27
  defined( 'ABSPATH' ) || exit;
39
  *
40
  * @since 2.0.0
41
  *
42
+ * @param \Square\SquareClient $api_client the API client
43
  */
44
  public function __construct( $api_client ) {
45
+ $this->square_api = $api_client->getLocationsApi();
 
46
  }
47
 
48
 
includes/API/Response.php CHANGED
@@ -22,8 +22,7 @@
22
  */
23
 
24
  namespace WooCommerce\Square\API;
25
-
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
 
28
  defined( 'ABSPATH' ) || exit;
29
 
@@ -32,13 +31,10 @@ defined( 'ABSPATH' ) || exit;
32
  *
33
  * @since 2.0.0
34
  */
35
- class Response implements Framework\SV_WC_API_Response {
36
-
37
-
38
  /** @var mixed raw response data */
39
  protected $raw_response_data;
40
 
41
-
42
  /**
43
  * Constructs the response object.
44
  *
@@ -73,8 +69,13 @@ class Response implements Framework\SV_WC_API_Response {
73
  * @return \stdClass[]
74
  */
75
  public function get_errors() {
 
 
 
 
 
76
 
77
- return ! empty( $this->raw_response_data->errors ) && is_array( $this->raw_response_data->errors ) ? $this->raw_response_data->errors : array();
78
  }
79
 
80
 
@@ -95,13 +96,12 @@ class Response implements Framework\SV_WC_API_Response {
95
  * Determines if the API response contains a particular error code.
96
  *
97
  * @since 2.1.6
98
- *
99
  * @return bool
100
  */
101
  public function has_error_code( $error_code ) {
102
-
103
  foreach ( $this->get_errors() as $error ) {
104
- if ( $error_code === $error->code ) {
105
  return true;
106
  }
107
  }
@@ -117,8 +117,15 @@ class Response implements Framework\SV_WC_API_Response {
117
  * @return string
118
  */
119
  public function to_string() {
 
 
 
 
 
 
 
120
 
121
- return is_callable( array( $this->get_data(), '__toString' ) ) ? $this->get_data() : '';
122
  }
123
 
124
 
22
  */
23
 
24
  namespace WooCommerce\Square\API;
25
+ use \WooCommerce\Square\Framework\Api\API_Response;
 
26
 
27
  defined( 'ABSPATH' ) || exit;
28
 
31
  *
32
  * @since 2.0.0
33
  */
34
+ class Response implements API_Response {
 
 
35
  /** @var mixed raw response data */
36
  protected $raw_response_data;
37
 
 
38
  /**
39
  * Constructs the response object.
40
  *
69
  * @return \stdClass[]
70
  */
71
  public function get_errors() {
72
+ if ( is_array( $this->raw_response_data ) && count( $this->raw_response_data ) > 0 ) {
73
+ if ( $this->raw_response_data[0] instanceof \Square\Models\Error ) {
74
+ return $this->raw_response_data;
75
+ }
76
+ }
77
 
78
+ return array();
79
  }
80
 
81
 
96
  * Determines if the API response contains a particular error code.
97
  *
98
  * @since 2.1.6
99
+ * @param $error \Square\Models\Error
100
  * @return bool
101
  */
102
  public function has_error_code( $error_code ) {
 
103
  foreach ( $this->get_errors() as $error ) {
104
+ if ( $error_code === $error->getCode() ) {
105
  return true;
106
  }
107
  }
117
  * @return string
118
  */
119
  public function to_string() {
120
+ $response_data = $this->get_data();
121
+
122
+ if ( is_callable( array( $response_data, '__toString' ) ) ) {
123
+ return $this->get_data();
124
+ } else if ( is_callable( array( $response_data, 'jsonSerialize' ) ) ) {
125
+ return wp_json_encode( $response_data, JSON_PRETTY_PRINT );
126
+ }
127
 
128
+ return '';
129
  }
130
 
131
 
includes/API/Responses/Catalog.php CHANGED
@@ -23,7 +23,6 @@
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
  use WooCommerce\Square\API\Response;
28
 
29
  defined( 'ABSPATH' ) || exit;
@@ -33,7 +32,7 @@ defined( 'ABSPATH' ) || exit;
33
  *
34
  * @since 2.0.0
35
  *
36
- * @method \SquareConnect\Model\ListCatalogResponse|\SquareConnect\Model\BatchUpsertCatalogObjectsResponse|\SquareConnect\Model\SearchCatalogObjectsResponse|\SquareConnect\Model\RetrieveCatalogObjectResponse|\SquareConnect\Model\CatalogInfoResponse get_data()
37
  */
38
  class Catalog extends Response {
39
 
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
 
26
  use WooCommerce\Square\API\Response;
27
 
28
  defined( 'ABSPATH' ) || exit;
32
  *
33
  * @since 2.0.0
34
  *
35
+ * @method \Square\Models\ListCatalogResponse|\Square\Models\BatchUpsertCatalogObjectsResponse|\Square\Models\SearchCatalogObjectsResponse|\Square\Models\RetrieveCatalogObjectResponse|\Square\Models\CatalogInfoResponse get_data()
36
  */
37
  class Catalog extends Response {
38
 
includes/API/Responses/Connection_Refresh_Response.php CHANGED
@@ -22,11 +22,10 @@
22
  */
23
 
24
  namespace WooCommerce\Square\API\Responses;
 
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
29
-
30
  /**
31
  * The connection refresh response class.
32
  *
@@ -34,8 +33,7 @@ use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
34
  *
35
  * @since 2.0.0
36
  */
37
- class Connection_Refresh_Response extends Framework\SV_WC_API_JSON_Response {
38
-
39
 
40
  /**
41
  * Gets the access token, if any.
@@ -95,6 +93,4 @@ class Connection_Refresh_Response extends Framework\SV_WC_API_JSON_Response {
95
 
96
  return ! empty( $this->response_data->error );
97
  }
98
-
99
-
100
  }
22
  */
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
+ use WooCommerce\Square\Framework\Api\API_JSON_Response;
26
 
27
  defined( 'ABSPATH' ) || exit;
28
 
 
 
29
  /**
30
  * The connection refresh response class.
31
  *
33
  *
34
  * @since 2.0.0
35
  */
36
+ class Connection_Refresh_Response extends API_JSON_Response {
 
37
 
38
  /**
39
  * Gets the access token, if any.
93
 
94
  return ! empty( $this->response_data->error );
95
  }
 
 
96
  }
includes/API/Responses/Inventory.php CHANGED
@@ -23,8 +23,7 @@
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect\Model\BatchRetrieveInventoryCountsResponse;
28
  use WooCommerce\Square\API\Response;
29
 
30
  defined( 'ABSPATH' ) || exit;
@@ -42,7 +41,7 @@ class Inventory extends Response {
42
  *
43
  * @since 2.0.0
44
  *
45
- * @return \SquareConnect\Model\InventoryCount[] array of inventory count objects
46
  */
47
  public function get_counts() {
48
 
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
26
+ use Square\Models\BatchRetrieveInventoryCountsResponse;
 
27
  use WooCommerce\Square\API\Response;
28
 
29
  defined( 'ABSPATH' ) || exit;
41
  *
42
  * @since 2.0.0
43
  *
44
+ * @return \Square\Models\InventoryCount[] array of inventory count objects
45
  */
46
  public function get_counts() {
47
 
includes/API/Responses/Locations.php CHANGED
@@ -23,8 +23,6 @@
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
- use SquareConnect\Model as SquareModel;
28
  use WooCommerce\Square\API\Response;
29
 
30
  defined( 'ABSPATH' ) || exit;
@@ -34,7 +32,7 @@ defined( 'ABSPATH' ) || exit;
34
  *
35
  * @since 2.0.0
36
  *
37
- * @method SquareModel\ListLocationsResponse get_data()
38
  */
39
  class Locations extends Response {
40
 
@@ -44,7 +42,7 @@ class Locations extends Response {
44
  *
45
  * @since 2.0.0
46
  *
47
- * @return SquareModel\Location[]
48
  */
49
  public function get_locations() {
50
 
23
 
24
  namespace WooCommerce\Square\API\Responses;
25
 
 
 
26
  use WooCommerce\Square\API\Response;
27
 
28
  defined( 'ABSPATH' ) || exit;
32
  *
33
  * @since 2.0.0
34
  *
35
+ * @method \Square\Models\ListLocationsResponse get_data()
36
  */
37
  class Locations extends Response {
38
 
42
  *
43
  * @since 2.0.0
44
  *
45
+ * @return \Square\Models\Location[]
46
  */
47
  public function get_locations() {
48
 
includes/Admin.php CHANGED
@@ -183,7 +183,6 @@ class Admin {
183
  'is_inventory_sync_enabled' => $this->get_plugin()->get_settings_handler()->is_inventory_sync_enabled(),
184
  'is_sandbox' => $this->get_plugin()->get_settings_handler()->is_sandbox(),
185
  'existing_sync_job_id' => $existing_sync_id,
186
- 'sync_in_background' => $this->get_plugin()->get_sync_handler()->should_sync_in_background(),
187
  'import_products_from_square' => wp_create_nonce( 'import-products-from-square' ),
188
  'sync_products_with_square' => wp_create_nonce( 'sync-products-with-square' ),
189
  'get_sync_with_square_status_nonce' => wp_create_nonce( 'get-sync-with-square-status' ),
183
  'is_inventory_sync_enabled' => $this->get_plugin()->get_settings_handler()->is_inventory_sync_enabled(),
184
  'is_sandbox' => $this->get_plugin()->get_settings_handler()->is_sandbox(),
185
  'existing_sync_job_id' => $existing_sync_id,
 
186
  'import_products_from_square' => wp_create_nonce( 'import-products-from-square' ),
187
  'sync_products_with_square' => wp_create_nonce( 'sync-products-with-square' ),
188
  'get_sync_with_square_status_nonce' => wp_create_nonce( 'get-sync-with-square-status' ),
includes/Admin/Privacy.php CHANGED
@@ -25,8 +25,6 @@ namespace WooCommerce\Square\Admin;
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
29
-
30
  /**
31
  * Privacy admin handler.
32
  *
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
 
 
28
  /**
29
  * Privacy admin handler.
30
  *
includes/Admin/Settings_Page.php CHANGED
@@ -25,7 +25,6 @@ namespace WooCommerce\Square\Admin;
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
29
  use WooCommerce\Square;
30
 
31
  /**
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
 
28
  use WooCommerce\Square;
29
 
30
  /**
includes/Admin/Sync_Page.php CHANGED
@@ -25,7 +25,6 @@ namespace WooCommerce\Square\Admin;
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
29
  use WooCommerce\Square\Handlers\Product;
30
  use WooCommerce\Square\Sync\Records;
31
 
25
 
26
  defined( 'ABSPATH' ) || exit;
27
 
 
28
  use WooCommerce\Square\Handlers\Product;
29
  use WooCommerce\Square\Sync\Records;
30
 
includes/Emails/Access_Token_Email.php CHANGED
@@ -23,8 +23,6 @@
23
 
24
  namespace WooCommerce\Square\Emails;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
-
28
  defined( 'ABSPATH' ) || exit;
29
 
30
  /**
23
 
24
  namespace WooCommerce\Square\Emails;
25
 
 
 
26
  defined( 'ABSPATH' ) || exit;
27
 
28
  /**
includes/Emails/Base_Email.php CHANGED
@@ -23,7 +23,7 @@
23
 
24
  namespace WooCommerce\Square\Emails;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
 
28
  defined( 'ABSPATH' ) || exit;
29
 
@@ -106,7 +106,7 @@ class Base_Email extends \WC_Email {
106
  }
107
 
108
  // add a recipient field
109
- $form_fields = Framework\SV_WC_Helper::array_insert_after(
110
  $form_fields,
111
  isset( $form_fields['enabled'] ) ? 'enabled' : key( $form_fields ),
112
  array(
23
 
24
  namespace WooCommerce\Square\Emails;
25
 
26
+ use WooCommerce\Square\Framework\Square_Helper;
27
 
28
  defined( 'ABSPATH' ) || exit;
29
 
106
  }
107
 
108
  // add a recipient field
109
+ $form_fields = Square_Helper::array_insert_after(
110
  $form_fields,
111
  isset( $form_fields['enabled'] ) ? 'enabled' : key( $form_fields ),
112
  array(
includes/Emails/Sync_Completed.php CHANGED
@@ -1,29 +1,17 @@
1
  <?php
2
  /**
3
- * WooCommerce Square
4
  *
5
- * This source file is subject to the GNU General Public License v3.0
6
- * that is bundled with this package in the file license.txt.
7
- * It is also available through the world-wide-web at this URL:
8
- * http://www.gnu.org/licenses/gpl-3.0.html
9
- * If you did not receive a copy of the license and are unable to
10
- * obtain it through the world-wide-web, please send an email
11
- * to license@woocommerce.com so we can send you a copy immediately.
12
  *
13
- * DISCLAIMER
14
- *
15
- * Do not edit or add to this file if you wish to upgrade WooCommerce Square to newer
16
- * versions in the future. If you wish to customize WooCommerce Square for your
17
- * needs please refer to https://docs.woocommerce.com/document/woocommerce-square/
18
- *
19
- * @author WooCommerce
20
- * @copyright Copyright: (c) 2019, Automattic, Inc.
21
- * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
22
  */
23
 
24
  namespace WooCommerce\Square\Emails;
25
 
26
- use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27
 
28
  defined( 'ABSPATH' ) || exit;
29
 
@@ -226,7 +214,7 @@ class Sync_Completed extends Base_Email {
226
  );
227
 
228
  // TODO update handling when WooCommerce 3.2 is the minimum required version {FN 2019-05-03}
229
- if ( Framework\SV_WC_Plugin_Compatibility::is_wc_version_gte( '3.2' ) ) {
230
  foreach ( $email_merge_tags as $find => $replace ) {
231
  $this->placeholders[ '{' . $find . '}' ] = $replace;
232
  }
1
  <?php
2
  /**
3
+ * Sync Completed Email class
4
  *
5
+ * Contains class that adds functionality to send out emails
6
+ * whenever sync is completed.
 
 
 
 
 
7
  *
8
+ * @package WooCommerce Square
9
+ * @since 2.0.0
 
 
 
 
 
 
 
10
  */
11
 
12
  namespace WooCommerce\Square\Emails;
13
 
14
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
15
 
16
  defined( 'ABSPATH' ) || exit;
17
 
214
  );
215
 
216
  // TODO update handling when WooCommerce 3.2 is the minimum required version {FN 2019-05-03}
217
+ if ( Plugin_Compatibility::is_wc_version_gte( '3.2' ) ) {
218
  foreach ( $email_merge_tags as $find => $replace ) {
219
  $this->placeholders[ '{' . $find . '}' ] = $replace;
220
  }
includes/Framework/Addresses/Address.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Addresses;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ /**
7
+ * The base address data class.
8
+ *
9
+ * This serves as a standard address object to be passed around by plugins whenever dealing with address data, and
10
+ * eliminates the need to rely on WooCommerce's address arrays.
11
+ *
12
+ * @since 3.0.0
13
+ */
14
+ class Address {
15
+
16
+
17
+ /** @var string line 1 of the street address */
18
+ protected $line_1 = '';
19
+
20
+ /** @var string line 2 of the street address */
21
+ protected $line_2 = '';
22
+
23
+ /** @var string line 3 of the street address */
24
+ protected $line_3 = '';
25
+
26
+ /** @var string address locality (city) */
27
+ protected $locality = '';
28
+
29
+ /** @var string address region (state) */
30
+ protected $region = '';
31
+
32
+ /** @var string address country */
33
+ protected $country = '';
34
+
35
+ /** @var string address postcode */
36
+ protected $postcode = '';
37
+
38
+
39
+ /** Getter methods ************************************************************************************************/
40
+
41
+
42
+ /**
43
+ * Gets line 1 of the street address.
44
+ *
45
+ * @since 3.0.0
46
+ *
47
+ * @return string
48
+ */
49
+ public function get_line_1() {
50
+
51
+ return $this->line_1;
52
+ }
53
+
54
+
55
+ /**
56
+ * Gets line 2 of the street address.
57
+ *
58
+ * @since 3.0.0
59
+ *
60
+ * @return string
61
+ */
62
+ public function get_line_2() {
63
+
64
+ return $this->line_2;
65
+ }
66
+
67
+
68
+ /**
69
+ * Gets line 3 of the street address.
70
+ *
71
+ * @since 3.0.0
72
+ *
73
+ * @return string
74
+ */
75
+ public function get_line_3() {
76
+
77
+ return $this->line_3;
78
+ }
79
+
80
+
81
+ /**
82
+ * Gets the locality or city.
83
+ *
84
+ * @since 3.0.0
85
+ *
86
+ * @return string
87
+ */
88
+ public function get_locality() {
89
+
90
+ return $this->locality;
91
+ }
92
+
93
+
94
+ /**
95
+ * Gets the region or state.
96
+ *
97
+ * @since 3.0.0
98
+ *
99
+ * @return string
100
+ */
101
+ public function get_region() {
102
+
103
+ return $this->region;
104
+ }
105
+
106
+
107
+ /**
108
+ * Gets the country.
109
+ *
110
+ * @since 3.0.0
111
+ *
112
+ * @return string
113
+ */
114
+ public function get_country() {
115
+
116
+ return $this->country;
117
+ }
118
+
119
+
120
+ /**
121
+ * Gets the postcode.
122
+ *
123
+ * @since 3.0.0
124
+ *
125
+ * @return string
126
+ */
127
+ public function get_postcode() {
128
+
129
+ return $this->postcode;
130
+ }
131
+
132
+
133
+ /**
134
+ * Gets the hash representation of this address.
135
+ *
136
+ * @see Address::get_hash_data()
137
+ *
138
+ * @since 3.0.0
139
+ *
140
+ * @return string
141
+ */
142
+ public function get_hash() {
143
+
144
+ return md5( wp_json_encode( $this->get_hash_data() ) );
145
+ }
146
+
147
+
148
+ /**
149
+ * Gets the data used to generate a hash for the address.
150
+ *
151
+ * @since 3.0.0
152
+ *
153
+ * @return string[]
154
+ */
155
+ protected function get_hash_data() {
156
+
157
+ return array(
158
+ $this->get_line_1(),
159
+ $this->get_line_2(),
160
+ $this->get_line_3(),
161
+ $this->get_locality(),
162
+ $this->get_region(),
163
+ $this->get_country(),
164
+ $this->get_postcode(),
165
+ );
166
+ }
167
+
168
+
169
+ /** Setter methods ************************************************************************************************/
170
+
171
+
172
+ /**
173
+ * Sets line 1 of the street address.
174
+ *
175
+ * @since 3.0.0
176
+ *
177
+ * @param string $value line 1 value
178
+ */
179
+ public function set_line_1( $value ) {
180
+
181
+ $this->line_1 = $value;
182
+ }
183
+
184
+
185
+ /**
186
+ * Sets line 2 of the street address.
187
+ *
188
+ * @since 3.0.0
189
+ *
190
+ * @param string $value line 2 value
191
+ */
192
+ public function set_line_2( $value ) {
193
+
194
+ $this->line_2 = $value;
195
+ }
196
+
197
+
198
+ /**
199
+ * Gets line 3 of the street address.
200
+ *
201
+ * @since 3.0.0
202
+ *
203
+ * @param string $value line 3 value
204
+ */
205
+ public function set_line_3( $value ) {
206
+
207
+ $this->line_3 = $value;
208
+ }
209
+
210
+
211
+ /**
212
+ * Gets the locality or city.
213
+ *
214
+ * @since 3.0.0
215
+ *
216
+ * @param string $value locality value
217
+ */
218
+ public function set_locality( $value ) {
219
+
220
+ $this->locality = $value;
221
+ }
222
+
223
+
224
+ /**
225
+ * Gets the region or state.
226
+ *
227
+ * @since 3.0.0
228
+ *
229
+ * @param string $value region value
230
+ */
231
+ public function set_region( $value ) {
232
+
233
+ $this->region = $value;
234
+ }
235
+
236
+
237
+ /**
238
+ * Sets the country.
239
+ *
240
+ * @since 3.0.0
241
+ *
242
+ * @param string $value country value
243
+ */
244
+ public function set_country( $value ) {
245
+
246
+ $this->country = $value;
247
+ }
248
+
249
+
250
+ /**
251
+ * Sets the postcode.
252
+ *
253
+ * @since 3.0.0
254
+ *
255
+ * @param string $value postcode value
256
+ */
257
+ public function set_postcode( $value ) {
258
+
259
+ $this->postcode = $value;
260
+ }
261
+
262
+
263
+ }
includes/Framework/Addresses/Customer_Address.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Addresses;
3
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * The customer address data class.
9
+ *
10
+ * Adds customer-specific data to a base address, as used for a billing or shipping address that can include first
11
+ * and last name.
12
+ *
13
+ * @see Address
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Customer_Address extends Address {
18
+
19
+
20
+ /** @var string customer first name */
21
+ protected $first_name = '';
22
+
23
+ /** @var string customer last name */
24
+ protected $last_name = '';
25
+
26
+
27
+ /** Getter Methods ************************************************************************************************/
28
+
29
+
30
+ /**
31
+ * Gets the customer first name.
32
+ *
33
+ * @since 3.0.0
34
+ *
35
+ * @return string
36
+ */
37
+ public function get_first_name() {
38
+
39
+ return $this->first_name;
40
+ }
41
+
42
+
43
+ /**
44
+ * Gets the customer first name.
45
+ *
46
+ * @since 3.0.0
47
+ *
48
+ * @return string
49
+ */
50
+ public function get_last_name() {
51
+
52
+ return $this->last_name;
53
+ }
54
+
55
+
56
+ /**
57
+ * Gets the data used to generate a hash for the address.
58
+ *
59
+ * @see Address::get_hash_data()
60
+ *
61
+ * @since 3.0.0
62
+ *
63
+ * @return string[]
64
+ */
65
+ protected function get_hash_data() {
66
+
67
+ // add the first & last name to data used to generate the hash
68
+ $data = array_merge(
69
+ array(
70
+ $this->get_first_name(),
71
+ $this->get_last_name(),
72
+ ),
73
+ parent::get_hash_data()
74
+ );
75
+
76
+ return $data;
77
+ }
78
+
79
+
80
+ /** Setter Methods ************************************************************************************************/
81
+
82
+
83
+ /**
84
+ * Sets the customer first name.
85
+ *
86
+ * @since 3.0.0
87
+ *
88
+ * @param string $value first name value
89
+ */
90
+ public function set_first_name( $value ) {
91
+
92
+ $this->first_name = $value;
93
+ }
94
+
95
+
96
+ /**
97
+ * Sets the customer last name.
98
+ *
99
+ * @since 3.0.0
100
+ *
101
+ * @param string $value first name value
102
+ */
103
+ public function set_last_name( $value ) {
104
+
105
+ $this->last_name = $value;
106
+ }
107
+
108
+
109
+ /**
110
+ * Sets the full address based on a WooCommerce order.
111
+ *
112
+ * @since 3.0.0
113
+ *
114
+ * @param \WC_Order $order WooCommerce order object
115
+ * @param string $type address type, like billing or shipping
116
+ */
117
+ public function set_from_order( \WC_Order $order, $type = 'billing' ) {
118
+
119
+ $this->set_first_name( Order_Compatibility::get_prop( $order, "{$type}_first_name" ) );
120
+ $this->set_last_name( Order_Compatibility::get_prop( $order, "{$type}_last_name" ) );
121
+ $this->set_line_1( Order_Compatibility::get_prop( $order, "{$type}_address_1" ) );
122
+ $this->set_line_2( Order_Compatibility::get_prop( $order, "{$type}_address_2" ) );
123
+ $this->set_locality( Order_Compatibility::get_prop( $order, "{$type}_city" ) );
124
+ $this->set_region( Order_Compatibility::get_prop( $order, "{$type}_state" ) );
125
+ $this->set_country( Order_Compatibility::get_prop( $order, "{$type}_country" ) );
126
+ $this->set_postcode( Order_Compatibility::get_prop( $order, "{$type}_postcode" ) );
127
+ }
128
+ }
includes/Framework/Admin_Message_Handler.php ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ /**
7
+ * # WordPress Admin Message Handler Class
8
+ *
9
+ * This class provides a reusable wordpress admin messaging facility for setting
10
+ * and displaying messages and error messages across admin page requests without
11
+ * resorting to passing the messages as query vars.
12
+ *
13
+ * ## Usage
14
+ *
15
+ * To use simple instantiate the class then set one or more messages:
16
+ *
17
+ * `
18
+ * $admin_message_handler = new WP_Admin_Message_Handler( __FILE__ );
19
+ * $admin_message_handler->add_message( 'Hello World!' );
20
+ * `
21
+ *
22
+ * Then show the messages wherever you need, either with the built-in method
23
+ * or by writing your own:
24
+ *
25
+ * `$admin_message_handler->show_messages();`
26
+ */
27
+ class Admin_Message_Handler {
28
+
29
+
30
+ /** transient message prefix */
31
+ const MESSAGE_TRANSIENT_PREFIX = '_wp_admin_message_';
32
+
33
+ /** the message id GET name */
34
+ const MESSAGE_ID_GET_NAME = 'wpamhid';
35
+
36
+
37
+ /** @var string unique message identifier, defaults to __FILE__ unless otherwise set */
38
+ private $message_id;
39
+
40
+ /** @var array array of messages */
41
+ private $messages = array();
42
+
43
+ /** @var array array of error messages */
44
+ private $errors = array();
45
+
46
+ /** @var array array of warning messages */
47
+ private $warnings = array();
48
+
49
+ /** @var array array of info messages */
50
+ private $infos = array();
51
+
52
+
53
+ /**
54
+ * Construct and initialize the admin message handler class
55
+ *
56
+ * @since 3.0.0
57
+ * @param string $message_id optional message id. Best practice is to set
58
+ * this to a unique identifier based on the client plugin, such as __FILE__
59
+ */
60
+ public function __construct( $message_id = null ) {
61
+
62
+ $this->message_id = $message_id;
63
+
64
+ // load any available messages
65
+ $this->load_messages();
66
+
67
+ add_filter( 'wp_redirect', array( $this, 'redirect' ), 1, 2 );
68
+ }
69
+
70
+
71
+ /**
72
+ * Persist messages
73
+ *
74
+ * @since 3.0.0
75
+ * @return boolean true if any messages were set, false otherwise
76
+ */
77
+ public function set_messages() {
78
+
79
+ // any messages to persist?
80
+ if ( $this->message_count() > 0 || $this->info_count() > 0 || $this->warning_count() > 0 || $this->error_count() > 0 ) {
81
+
82
+ set_transient(
83
+ self::MESSAGE_TRANSIENT_PREFIX . $this->get_message_id(),
84
+ array(
85
+ 'errors' => $this->errors,
86
+ 'warnings' => $this->warnings,
87
+ 'infos' => $this->infos,
88
+ 'messages' => $this->messages,
89
+ ),
90
+ 60 * 60
91
+ );
92
+
93
+ return true;
94
+ }
95
+
96
+ return false;
97
+ }
98
+
99
+
100
+ /**
101
+ * Loads messages
102
+ *
103
+ * @since 3.0.0
104
+ */
105
+ public function load_messages() {
106
+
107
+ if ( isset( $_GET[ self::MESSAGE_ID_GET_NAME ] ) && $this->get_message_id() == $_GET[ self::MESSAGE_ID_GET_NAME ] ) {
108
+
109
+ $memo = get_transient( self::MESSAGE_TRANSIENT_PREFIX . $_GET[ self::MESSAGE_ID_GET_NAME ] );
110
+
111
+ if ( isset( $memo['errors'] ) ) $this->errors = $memo['errors'];
112
+ if ( isset( $memo['warnings'] ) ) $this->warnings = $memo['warnings'];
113
+ if ( isset( $memo['infos'] ) ) $this->infos = $memo['infos'];
114
+ if ( isset( $memo['messages'] ) ) $this->messages = $memo['messages'];
115
+
116
+ $this->clear_messages( $_GET[ self::MESSAGE_ID_GET_NAME ] );
117
+ }
118
+ }
119
+
120
+
121
+ /**
122
+ * Clear messages and errors
123
+ *
124
+ * @since 3.0.0
125
+ * @param string $id the messages identifier
126
+ */
127
+ public function clear_messages( $id ) {
128
+ delete_transient( self::MESSAGE_TRANSIENT_PREFIX . $id );
129
+ }
130
+
131
+
132
+ /**
133
+ * Add an error message.
134
+ *
135
+ * @since 3.0.0
136
+ * @param string $error error message
137
+ */
138
+ public function add_error( $error ) {
139
+ $this->errors[] = $error;
140
+ }
141
+
142
+
143
+ /**
144
+ * Adds a warning message.
145
+ *
146
+ * @since 3.0.0
147
+ *
148
+ * @param string $message warning message to add
149
+ */
150
+ public function add_warning( $message ) {
151
+ $this->warnings[] = $message;
152
+ }
153
+
154
+ /**
155
+ * Add a message.
156
+ *
157
+ * @since 3.0.0
158
+ * @param string $message the message to add
159
+ */
160
+ public function add_message( $message ) {
161
+ $this->messages[] = $message;
162
+ }
163
+
164
+
165
+ /**
166
+ * Get error count.
167
+ *
168
+ * @since 3.0.0
169
+ * @return int error message count
170
+ */
171
+ public function error_count() {
172
+ return sizeof( $this->errors );
173
+ }
174
+
175
+
176
+ /**
177
+ * Gets the warning message count.
178
+ *
179
+ * @since 3.0.0
180
+ *
181
+ * @return int warning message count
182
+ */
183
+ public function warning_count() {
184
+ return sizeof( $this->warnings );
185
+ }
186
+
187
+
188
+ /**
189
+ * Gets the info message count.
190
+ *
191
+ * @since 3.0.0
192
+ *
193
+ * @return int info message count
194
+ */
195
+ public function info_count() {
196
+ return sizeof( $this->infos );
197
+ }
198
+
199
+
200
+ /**
201
+ * Get message count.
202
+ *
203
+ * @since 3.0.0
204
+ * @return int message count
205
+ */
206
+ public function message_count() {
207
+ return sizeof( $this->messages );
208
+ }
209
+
210
+
211
+ /**
212
+ * Get error messages
213
+ *
214
+ * @since 3.0.0
215
+ * @return array of error message strings
216
+ */
217
+ public function get_errors() {
218
+ return $this->errors;
219
+ }
220
+
221
+
222
+ /**
223
+ * Get an error message
224
+ *
225
+ * @since 3.0.0
226
+ * @param int $index the error index
227
+ * @return string the error message
228
+ */
229
+ public function get_error( $index ) {
230
+ return isset( $this->errors[ $index ] ) ? $this->errors[ $index ] : '';
231
+ }
232
+
233
+
234
+ /**
235
+ * Gets all warning messages.
236
+ *
237
+ * @since 3.0.0
238
+ *
239
+ * @return array
240
+ */
241
+ public function get_warnings() {
242
+ return $this->warnings;
243
+ }
244
+
245
+
246
+ /**
247
+ * Gets a specific warning message.
248
+ *
249
+ * @since 3.0.0
250
+ *
251
+ * @param int $index warning message index
252
+ * @return string
253
+ */
254
+ public function get_warning( $index ) {
255
+ return isset( $this->warnings[ $index ] ) ? $this->warnings[ $index ] : '';
256
+ }
257
+
258
+
259
+ /**
260
+ * Gets all info messages.
261
+ *
262
+ * @since 3.0.0
263
+ *
264
+ * @return array
265
+ */
266
+ public function get_infos() {
267
+ return $this->infos;
268
+ }
269
+
270
+
271
+ /**
272
+ * Gets a specific info message.
273
+ *
274
+ * @since 3.0.0
275
+ *
276
+ * @param int $index info message index
277
+ * @return string
278
+ */
279
+ public function get_info( $index ) {
280
+ return isset( $this->infos[ $index ] ) ? $this->infos[ $index ] : '';
281
+ }
282
+
283
+
284
+ /**
285
+ * Get messages
286
+ *
287
+ * @since 3.0.0
288
+ * @return array of message strings
289
+ */
290
+ public function get_messages() {
291
+ return $this->messages;
292
+ }
293
+
294
+
295
+ /**
296
+ * Get a message
297
+ *
298
+ * @since 3.0.0
299
+ * @param int $index the message index
300
+ * @return string the message
301
+ */
302
+ public function get_message( $index ) {
303
+ return isset( $this->messages[ $index ] ) ? $this->messages[ $index ] : '';
304
+ }
305
+
306
+
307
+ /**
308
+ * Render the errors and messages.
309
+ *
310
+ * @since 3.0.0
311
+ * @param array $params {
312
+ * Optional parameters.
313
+ *
314
+ * @type array $capabilities Any user capabilities to check if the user is allowed to view the messages,
315
+ * default: `manage_woocommerce`
316
+ * }
317
+ */
318
+ public function show_messages( $params = array() ) {
319
+
320
+ $params = wp_parse_args( $params, array(
321
+ 'capabilities' => array(
322
+ 'manage_woocommerce',
323
+ ),
324
+ ) );
325
+
326
+ $check_user_capabilities = array();
327
+
328
+ // check if user has at least one capability that allows to see messages
329
+ foreach ( $params['capabilities'] as $capability ) {
330
+ $check_user_capabilities[] = current_user_can( $capability );
331
+ }
332
+
333
+ // bail out if user has no minimum capabilities to see messages
334
+ if ( ! in_array( true, $check_user_capabilities, true ) ) {
335
+ return;
336
+ }
337
+
338
+ $output = '';
339
+
340
+ if ( $this->error_count() > 0 ) {
341
+ $output .= '<div id="wp-admin-message-handler-error" class="notice-error notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_errors() ) . '</strong></li></ul></div>';
342
+ }
343
+
344
+ if ( $this->warning_count() > 0 ) {
345
+ $output .= '<div id="wp-admin-message-handler-warning" class="notice-warning notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_warnings() ) . '</strong></li></ul></div>';
346
+ }
347
+
348
+ if ( $this->info_count() > 0 ) {
349
+ $output .= '<div id="wp-admin-message-handler-warning" class="notice-info notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_infos() ) . '</strong></li></ul></div>';
350
+ }
351
+
352
+ if ( $this->message_count() > 0 ) {
353
+ $output .= '<div id="wp-admin-message-handler-message" class="notice-success notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_messages() ) . '</strong></li></ul></div>';
354
+ }
355
+
356
+ echo wp_kses_post( $output );
357
+ }
358
+
359
+
360
+ /**
361
+ * Redirection hook which persists messages into session data.
362
+ *
363
+ * @since 3.0.0
364
+ * @param string $location the URL to redirect to
365
+ * @param int $status the http status
366
+ * @return string the URL to redirect to
367
+ */
368
+ public function redirect( $location, $status ) {
369
+
370
+ // add the admin message id param to the
371
+ if ( $this->set_messages() ) {
372
+ $location = add_query_arg( self::MESSAGE_ID_GET_NAME, rawurlencode( $this->get_message_id() ), $location );
373
+ }
374
+
375
+ return $location;
376
+ }
377
+
378
+
379
+ /**
380
+ * Generate a unique id to identify the messages
381
+ *
382
+ * @since 3.0.0
383
+ * @return string unique identifier
384
+ */
385
+ protected function get_message_id() {
386
+
387
+ if ( ! isset( $this->message_id ) ) $this->message_id = __FILE__;
388
+
389
+ return wp_create_nonce( $this->message_id );
390
+
391
+ }
392
+ }
includes/Framework/Admin_Notice_Handler.php ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ /**
7
+ * Admin Notice Handler Class
8
+ *
9
+ * The purpose of this class is to provide a facility for displaying
10
+ * conditional (often dismissible) admin notices during a single page
11
+ * request
12
+ *
13
+ * @since 3.0.0
14
+ */
15
+ class Admin_Notice_Handler {
16
+
17
+
18
+ /** @var Plugin the plugin */
19
+ private $plugin;
20
+
21
+ /** @var array associative array of id to notice text */
22
+ private $admin_notices = array();
23
+
24
+ /** @var boolean static member to enforce a single rendering of the admin notice placeholder element */
25
+ static private $admin_notice_placeholder_rendered = false;
26
+
27
+ /** @var boolean static member to enforce a single rendering of the admin notice javascript */
28
+ static private $admin_notice_js_rendered = false;
29
+
30
+
31
+ /**
32
+ * Initialize and setup the Admin Notice Handler
33
+ *
34
+ * @since 3.0.0
35
+ */
36
+ public function __construct( $plugin ) {
37
+
38
+ $this->plugin = $plugin;
39
+
40
+ // render any admin notices, delayed notices, and
41
+ add_action( 'admin_notices', array( $this, 'render_admin_notices' ), 15 );
42
+ add_action( 'admin_footer', array( $this, 'render_delayed_admin_notices' ), 15 );
43
+ add_action( 'admin_footer', array( $this, 'render_admin_notice_js' ), 20 );
44
+
45
+ // AJAX handler to dismiss any warning/error notices
46
+ add_action( 'wp_ajax_wc_plugin_framework_' . $this->get_plugin()->get_id() . '_dismiss_notice', array( $this, 'handle_dismiss_notice' ) );
47
+ }
48
+
49
+
50
+ /**
51
+ * Adds the given $message as a dismissible notice identified by $message_id,
52
+ * unless the notice has been dismissed, or we're on the plugin settings page
53
+ *
54
+ * @since 3.0.0
55
+ * @param string $message the notice message to display
56
+ * @param string $message_id the message id
57
+ * @param array $params {
58
+ * Optional parameters.
59
+ *
60
+ * @type bool $dismissible If the notice should be dismissible
61
+ * @type bool $always_show_on_settings If the notice should be forced to display on the
62
+ * plugin settings page, regardless of `$dismissible`.
63
+ * @type string $notice_class Additional classes for the notice.
64
+ * }
65
+ */
66
+ public function add_admin_notice( $message, $message_id, $params = array() ) {
67
+
68
+ $params = wp_parse_args( $params, array(
69
+ 'dismissible' => true,
70
+ 'always_show_on_settings' => true,
71
+ 'notice_class' => 'updated',
72
+ ) );
73
+
74
+ if ( $this->should_display_notice( $message_id, $params ) ) {
75
+ $this->admin_notices[ $message_id ] = array(
76
+ 'message' => $message,
77
+ 'rendered' => false,
78
+ 'params' => $params,
79
+ );
80
+ }
81
+ }
82
+
83
+
84
+ /**
85
+ * Returns true if the identified notice hasn't been cleared, or we're on
86
+ * the plugin settings page (where notices are always displayed)
87
+ *
88
+ * @since 3.0.0
89
+ * @param string $message_id the message id
90
+ * @param array $params {
91
+ * Optional parameters.
92
+ *
93
+ * @type bool $dismissible If the notice should be dismissible
94
+ * @type bool $always_show_on_settings If the notice should be forced to display on the
95
+ * plugin settings page, regardless of `$dismissible`.
96
+ * }
97
+ * @return bool
98
+ */
99
+ public function should_display_notice( $message_id, $params = array() ) {
100
+
101
+ // bail out if user is not a shop manager
102
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
103
+ return false;
104
+ }
105
+
106
+ $params = wp_parse_args( $params, array(
107
+ 'dismissible' => true,
108
+ 'always_show_on_settings' => true,
109
+ ) );
110
+
111
+ // if the notice is always shown on the settings page, and we're on the settings page
112
+ if ( $params['always_show_on_settings'] && $this->get_plugin()->is_plugin_settings() ) {
113
+ return true;
114
+ }
115
+
116
+ // non-dismissible, always display
117
+ if ( ! $params['dismissible'] ) {
118
+ return true;
119
+ }
120
+
121
+ // dismissible: display if notice has not been dismissed
122
+ return ! $this->is_notice_dismissed( $message_id );
123
+ }
124
+
125
+
126
+ /**
127
+ * Render any admin notices, as well as the admin notice placeholder
128
+ *
129
+ * @since 3.0.0
130
+ * @param boolean $is_visible true if the notices should be immediately visible, false otherwise
131
+ */
132
+ public function render_admin_notices( $is_visible = true ) {
133
+
134
+ // default for actions
135
+ if ( ! is_bool( $is_visible ) ) {
136
+ $is_visible = true;
137
+ }
138
+
139
+ foreach ( $this->admin_notices as $message_id => $message_data ) {
140
+ if ( ! $message_data['rendered'] ) {
141
+ $message_data['params']['is_visible'] = $is_visible;
142
+ $this->render_admin_notice( $message_data['message'], $message_id, $message_data['params'] );
143
+ $this->admin_notices[ $message_id ]['rendered'] = true;
144
+ }
145
+ }
146
+
147
+ if ( $is_visible && ! self::$admin_notice_placeholder_rendered ) {
148
+ // placeholder for moving delayed notices up into place
149
+ echo '<div class="js-wc-' . esc_attr( $this->get_plugin()->get_id_dasherized() ) . '-admin-notice-placeholder"></div>';
150
+ self::$admin_notice_placeholder_rendered = true;
151
+ }
152
+
153
+ }
154
+
155
+
156
+ /**
157
+ * Render any delayed admin notices, which have not yet already been rendered
158
+ *
159
+ * @since 3.0.0
160
+ */
161
+ public function render_delayed_admin_notices() {
162
+ $this->render_admin_notices( false );
163
+ }
164
+
165
+
166
+ /**
167
+ * Render a single admin notice
168
+ *
169
+ * @since 3.0.0
170
+ * @param string $message the notice message to display
171
+ * @param string $message_id the message id
172
+ * @param array $params {
173
+ * Optional parameters.
174
+ *
175
+ * @type bool $dismissible If the notice should be dismissible
176
+ * @type bool $is_visible If the notice should be immediately visible
177
+ * @type bool $always_show_on_settings If the notice should be forced to display on the
178
+ * plugin settings page, regardless of `$dismissible`.
179
+ * @type string $notice_class Additional classes for the notice.
180
+ * }
181
+ */
182
+ public function render_admin_notice( $message, $message_id, $params = array() ) {
183
+
184
+ $params = wp_parse_args( $params, array(
185
+ 'dismissible' => true,
186
+ 'is_visible' => true,
187
+ 'always_show_on_settings' => true,
188
+ 'notice_class' => 'updated',
189
+ ) );
190
+
191
+ $classes = array(
192
+ 'notice',
193
+ 'js-wc-plugin-framework-admin-notice',
194
+ $params['notice_class'],
195
+ );
196
+
197
+ // maybe make this notice dismissible
198
+ // uses a WP core class which handles the markup and styling
199
+ if ( $params['dismissible'] && ( ! $params['always_show_on_settings'] || ! $this->get_plugin()->is_plugin_settings() ) ) {
200
+ $classes[] = 'is-dismissible';
201
+ }
202
+
203
+ echo sprintf(
204
+ '<div class="%1$s" data-plugin-id="%2$s" data-message-id="%3$s" %4$s><p>%5$s</p></div>',
205
+ esc_attr( implode( ' ', $classes ) ),
206
+ esc_attr( $this->get_plugin()->get_id() ),
207
+ esc_attr( $message_id ),
208
+ ( ! $params['is_visible'] ) ? 'style="display:none;"' : '',
209
+ wp_kses_post( $message )
210
+ );
211
+ }
212
+
213
+
214
+ /**
215
+ * Render the javascript to handle the notice "dismiss" functionality
216
+ *
217
+ * @since 3.0.0
218
+ */
219
+ public function render_admin_notice_js() {
220
+
221
+ // if there were no notices, or we've already rendered the js, there's nothing to do
222
+ if ( empty( $this->admin_notices ) || self::$admin_notice_js_rendered ) {
223
+ return;
224
+ }
225
+
226
+ $plugin_slug = $this->get_plugin()->get_id_dasherized();
227
+
228
+ self::$admin_notice_js_rendered = true;
229
+
230
+ ob_start();
231
+ ?>
232
+
233
+ // Log dismissed notices
234
+ $( '.js-wc-plugin-framework-admin-notice' ).on( 'click.wp-dismiss-notice', '.notice-dismiss', function( e ) {
235
+
236
+ var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
237
+
238
+ log_dismissed_notice(
239
+ $( $notice ).data( 'plugin-id' ),
240
+ $( $notice ).data( 'message-id' )
241
+ );
242
+
243
+ } );
244
+
245
+ // Log and hide legacy notices
246
+ $( 'a.js-wc-plugin-framework-notice-dismiss' ).click( function( e ) {
247
+
248
+ e.preventDefault();
249
+
250
+ var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
251
+
252
+ log_dismissed_notice(
253
+ $( $notice ).data( 'plugin-id' ),
254
+ $( $notice ).data( 'message-id' )
255
+ );
256
+
257
+ $( $notice ).fadeOut();
258
+
259
+ } );
260
+
261
+ function log_dismissed_notice( pluginID, messageID ) {
262
+
263
+ $.get(
264
+ ajaxurl,
265
+ {
266
+ action: 'wc_plugin_framework_' + pluginID + '_dismiss_notice',
267
+ messageid: messageID
268
+ }
269
+ );
270
+ }
271
+
272
+ // move any delayed notices up into position .show();
273
+ $( '.js-wc-plugin-framework-admin-notice:hidden' ).insertAfter( '.js-wc-<?php echo esc_js( $plugin_slug ); ?>-admin-notice-placeholder' ).show();
274
+ <?php
275
+ $javascript = ob_get_clean();
276
+
277
+ wc_enqueue_js( $javascript );
278
+ }
279
+
280
+
281
+ /**
282
+ * Marks the identified admin notice as dismissed for the given user
283
+ *
284
+ * @since 3.0.0
285
+ * @param string $message_id the message identifier
286
+ * @param int $user_id optional user identifier, defaults to current user
287
+ */
288
+ public function dismiss_notice( $message_id, $user_id = null ) {
289
+
290
+ if ( is_null( $user_id ) ) {
291
+ $user_id = get_current_user_id();
292
+ }
293
+
294
+ $dismissed_notices = $this->get_dismissed_notices( $user_id );
295
+
296
+ $dismissed_notices[ $message_id ] = true;
297
+
298
+ update_user_meta( $user_id, '_wc_plugin_framework_' . $this->get_plugin()->get_id() . '_dismissed_messages', $dismissed_notices );
299
+
300
+ /**
301
+ * Admin Notice Dismissed Action.
302
+ *
303
+ * Fired when a user dismisses an admin notice.
304
+ *
305
+ * @since 3.0.0
306
+ * @param string $message_id notice identifier
307
+ * @param string|int $user_id
308
+ */
309
+ do_action( 'wc_' . $this->get_plugin()->get_id(). '_dismiss_notice', $message_id, $user_id );
310
+ }
311
+
312
+ /**
313
+ * Returns true if the identified admin notice has been dismissed for the
314
+ * given user
315
+ *
316
+ * @since 3.0.0
317
+ * @param string $message_id the message identifier
318
+ * @param int $user_id optional user identifier, defaults to current user
319
+ * @return boolean true if the message has been dismissed by the admin user
320
+ */
321
+ public function is_notice_dismissed( $message_id, $user_id = null ) {
322
+
323
+ $dismissed_notices = $this->get_dismissed_notices( $user_id );
324
+
325
+ return isset( $dismissed_notices[ $message_id ] ) && $dismissed_notices[ $message_id ];
326
+ }
327
+
328
+
329
+ /**
330
+ * Returns the full set of dismissed notices for the user identified by
331
+ * $user_id, for this plugin
332
+ *
333
+ * @since 3.0.0
334
+ * @param int $user_id optional user identifier, defaults to current user
335
+ * @return array of message id to dismissed status (true or false)
336
+ */
337
+ public function get_dismissed_notices( $user_id = null ) {
338
+
339
+ if ( is_null( $user_id ) ) {
340
+ $user_id = get_current_user_id();
341
+ }
342
+
343
+ $dismissed_notices = get_user_meta( $user_id, '_wc_plugin_framework_' . $this->get_plugin()->get_id() . '_dismissed_messages', true );
344
+
345
+ if ( empty( $dismissed_notices ) ) {
346
+ return array();
347
+ } else {
348
+ return $dismissed_notices;
349
+ }
350
+ }
351
+
352
+
353
+ /** AJAX methods ******************************************************/
354
+
355
+
356
+ /**
357
+ * Dismiss the identified notice
358
+ *
359
+ * @since 3.0.0
360
+ */
361
+ public function handle_dismiss_notice() {
362
+
363
+ $this->dismiss_notice( $_REQUEST['messageid'] );
364
+
365
+ }
366
+
367
+
368
+ /** Getter methods ******************************************************/
369
+
370
+
371
+ /**
372
+ * Get the plugin
373
+ *
374
+ * @since 3.0.0
375
+ * @return Plugin returns the plugin instance
376
+ */
377
+ protected function get_plugin() {
378
+ return $this->plugin;
379
+ }
380
+ }
includes/Framework/Api/API_JSON_Request.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\Api;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * Base JSON API request class.
9
+ *
10
+ * @since 3.0.0
11
+ */
12
+ abstract class API_JSON_Request implements API_Request {
13
+
14
+
15
+ /** @var string The request method, one of HEAD, GET, PUT, PATCH, POST, DELETE */
16
+ protected $method;
17
+
18
+ /** @var string The request path */
19
+ protected $path;
20
+
21
+ /** @var array The request parameters, if any */
22
+ protected $params = array();
23
+
24
+ /** @var array the request data */
25
+ protected $data = array();
26
+
27
+
28
+ /**
29
+ * Get the request method.
30
+ *
31
+ * @since 3.0.0
32
+ * @see API_Request::get_method()
33
+ * @return string
34
+ */
35
+ public function get_method() {
36
+ return $this->method;
37
+ }
38
+
39
+
40
+ /**
41
+ * Get the request path.
42
+ *
43
+ * @since 3.0.0
44
+ * @see API_Request::get_path()
45
+ * @return string
46
+ */
47
+ public function get_path() {
48
+ return $this->path;
49
+ }
50
+
51
+
52
+ /**
53
+ * Get the request parameters.
54
+ *
55
+ * @since 3.0.0
56
+ * @see API_Request::get_params()
57
+ * @return array
58
+ */
59
+ public function get_params() {
60
+ return $this->params;
61
+ }
62
+
63
+
64
+ /**
65
+ * Get the request data.
66
+ *
67
+ * @since 3.0.0
68
+ * @return array
69
+ */
70
+ public function get_data() {
71
+ return $this->data;
72
+ }
73
+
74
+
75
+ /** API Helper Methods ******************************************************/
76
+
77
+
78
+ /**
79
+ * Get the string representation of this request.
80
+ *
81
+ * @since 3.0.0
82
+ * @see API_Request::to_string()
83
+ * @return string
84
+ */
85
+ public function to_string() {
86
+
87
+ $data = $this->get_data();
88
+
89
+ return ! empty( $data ) ? wp_json_encode( $data ) : '';
90
+ }
91
+
92
+
93
+ /**
94
+ * Get the string representation of this request with any and all sensitive elements masked
95
+ * or removed.
96
+ *
97
+ * @since 3.0.0
98
+ * @see API_Request::to_string_safe()
99
+ * @return string
100
+ */
101
+ public function to_string_safe() {
102
+
103
+ return $this->to_string();
104
+ }
105
+ }
includes/Framework/Api/API_JSON_Response.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\Api;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * Base JSON API response class.
9
+ *
10
+ * @since 3.0.0
11
+ */
12
+ abstract class API_JSON_Response {
13
+
14
+ /** @var string string representation of this response */
15
+ protected $raw_response_json;
16
+
17
+ /** @var mixed decoded response data */
18
+ public $response_data;
19
+
20
+
21
+ /**
22
+ * Build the data object from the raw JSON.
23
+ *
24
+ * @since 3.0.0
25
+ * @param string $raw_response_json The raw JSON
26
+ */
27
+ public function __construct( $raw_response_json ) {
28
+ $this->raw_response_json = $raw_response_json;
29
+ $this->response_data = json_decode( $raw_response_json );
30
+ }
31
+
32
+
33
+ /**
34
+ * Magic accessor for response data attributes
35
+ *
36
+ * @since 3.0.0
37
+ * @param string $name The attribute name to get.
38
+ * @return mixed The attribute value
39
+ */
40
+ public function __get( $name ) {
41
+ // accessing the response_data object indirectly via attribute (useful when it's a class)
42
+ return isset( $this->response_data->$name ) ? $this->response_data->$name : null;
43
+ }
44
+
45
+
46
+ /**
47
+ * Get the string representation of this response.
48
+ *
49
+ * @since 3.0.0
50
+ * @return string
51
+ */
52
+ public function to_string() {
53
+ return $this->raw_response_json;
54
+ }
55
+
56
+
57
+ /**
58
+ * Get the string representation of this response with any and all sensitive elements masked
59
+ * or removed.
60
+ *
61
+ * @since 3.0.0
62
+ * @return string
63
+ */
64
+ public function to_string_safe() {
65
+ return $this->to_string();
66
+ }
67
+ }
includes/Framework/Api/API_Request.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Api;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ interface API_Request {
7
+ /**
8
+ * Returns the method for this request: one of HEAD, GET, PUT, PATCH, POST, DELETE
9
+ *
10
+ * @since 3.0.0
11
+ * @return string the request method, or null to use the API default
12
+ */
13
+ public function get_method();
14
+
15
+
16
+ /**
17
+ * Returns the request path
18
+ *
19
+ * @since 3.0.0
20
+ * @return string the request path, or '' if none
21
+ */
22
+ public function get_path();
23
+
24
+
25
+ /**
26
+ * Gets the request query params.
27
+ *
28
+ * @since 3.0.0
29
+ *
30
+ * @return array
31
+ */
32
+ public function get_params();
33
+
34
+
35
+ /**
36
+ * Gets the request data.
37
+ *
38
+ * @since 3.0.0
39
+ *
40
+ * @return array
41
+ */
42
+ public function get_data();
43
+
44
+
45
+ /**
46
+ * Returns the string representation of this request
47
+ *
48
+ * @since 3.0.0
49
+ * @return string the request
50
+ */
51
+ public function to_string();
52
+
53
+
54
+ /**
55
+ * Returns the string representation of this request with any and all
56
+ * sensitive elements masked or removed
57
+ *
58
+ * @since 3.0.0
59
+ * @return string the request, safe for logging/displaying
60
+ */
61
+ public function to_string_safe();
62
+ }
includes/Framework/Api/API_Response.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Api;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ interface API_Response {
7
+
8
+ /**
9
+ * Returns the string representation of this request
10
+ *
11
+ * @since 3.0.0
12
+ * @return string the request
13
+ */
14
+ public function to_string();
15
+
16
+
17
+ /**
18
+ * Returns the string representation of this request with any and all
19
+ * sensitive elements masked or removed
20
+ *
21
+ * @since 3.0.0
22
+ * @return string the request, safe for logging/displaying
23
+ */
24
+ public function to_string_safe();
25
+ }
includes/Framework/Api/Base.php ADDED
@@ -0,0 +1,659 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Api;
3
+
4
+ use WooCommerce;
5
+ use WooCommerce\Square\Framework\Square_Helper;
6
+
7
+ defined( 'ABSPATH' ) or exit;
8
+
9
+ /**
10
+ * Base API Class
11
+ *
12
+ * This class provides a standardized framework for constructing an API wrapper
13
+ * to external services. It is designed to be extremely flexible.
14
+ */
15
+ abstract class Base {
16
+
17
+ /** @var string request method, defaults to POST */
18
+ protected $request_method = 'POST';
19
+
20
+ /** @var string URI used for the request */
21
+ protected $request_uri;
22
+
23
+ /** @var array request headers */
24
+ protected $request_headers = array();
25
+
26
+ /** @var string request user-agent */
27
+ protected $request_user_agent;
28
+
29
+ /** @var string request HTTP version, defaults to 1.0 */
30
+ protected $request_http_version = '1.0';
31
+
32
+ /** @var string request duration */
33
+ protected $request_duration;
34
+
35
+ /** @var API_Request|object request */
36
+ protected $request;
37
+
38
+ /** @var string response code */
39
+ protected $response_code;
40
+
41
+ /** @var string response message */
42
+ protected $response_message;
43
+
44
+ /** @var array response headers */
45
+ protected $response_headers;
46
+
47
+ /** @var string raw response body */
48
+ protected $raw_response_body;
49
+
50
+ /** @var string response handler class name */
51
+ protected $response_handler;
52
+
53
+ /** @var API_Response|object response */
54
+ protected $response;
55
+
56
+ /**
57
+ * Perform the request and return the parsed response
58
+ *
59
+ * @since 3.0.0
60
+ *
61
+ * @param API_Request|object $request class instance which implements API_Request
62
+ * @return API_Response|object class instance which implements API_Response
63
+ * @throws API_Exception may be thrown in implementations
64
+ */
65
+ protected function perform_request( $request ) {
66
+
67
+ // ensure API is in its default state
68
+ $this->reset_response();
69
+
70
+ // save the request object
71
+ $this->request = $request;
72
+
73
+ $start_time = microtime( true );
74
+
75
+ // if this API requires TLS v1.2, force it
76
+ if ( $this->require_tls_1_2() ) {
77
+ add_action( 'http_api_curl', array( $this, 'set_tls_1_2_request' ), 10, 3 );
78
+ }
79
+
80
+ // perform the request
81
+ $response = $this->do_remote_request( $this->get_request_uri(), $this->get_request_args() );
82
+
83
+ // calculate request duration
84
+ $this->request_duration = round( microtime( true ) - $start_time, 5 );
85
+
86
+ try {
87
+
88
+ // parse & validate response
89
+ $response = $this->handle_response( $response );
90
+
91
+ } catch ( \Exception $e ) {
92
+
93
+ // alert other actors that a request has been made
94
+ $this->broadcast_request();
95
+
96
+ throw $e;
97
+ }
98
+
99
+ return $response;
100
+ }
101
+
102
+ /**
103
+ * Simple wrapper for wp_remote_request() so child classes can override this
104
+ * and provide their own transport mechanism if needed, e.g. a custom
105
+ * cURL implementation
106
+ *
107
+ * @since 3.0.0
108
+ *
109
+ * @param string $request_uri
110
+ * @param string $request_args
111
+ * @return array|\WP_Error
112
+ */
113
+ protected function do_remote_request( $request_uri, $request_args ) {
114
+
115
+ return wp_safe_remote_request( $request_uri, $request_args );
116
+ }
117
+
118
+ /**
119
+ * Handle and parse the response
120
+ *
121
+ * @since 3.0.0
122
+ * @param array|\WP_Error $response response data
123
+ * @throws \Exception network issues, timeouts, API errors, etc
124
+ * @return API_Request|object request class instance that implements API_Request
125
+ */
126
+ protected function handle_response( $response ) {
127
+
128
+ // check for WP HTTP API specific errors (network timeout, etc)
129
+ if ( is_wp_error( $response ) ) {
130
+ throw new \Exception( $response->get_error_message(), (int) $response->get_error_code() );
131
+ }
132
+
133
+ // set response data
134
+ $this->response_code = wp_remote_retrieve_response_code( $response );
135
+ $this->response_message = wp_remote_retrieve_response_message( $response );
136
+ $this->raw_response_body = wp_remote_retrieve_body( $response );
137
+
138
+ $response_headers = wp_remote_retrieve_headers( $response );
139
+
140
+ // WP 4.6+ returns an object
141
+ if ( is_object( $response_headers ) ) {
142
+ $response_headers = $response_headers->getAll();
143
+ }
144
+
145
+ $this->response_headers = $response_headers;
146
+
147
+ // parse the response body and tie it to the request
148
+ $this->response = $this->get_parsed_response( $this->raw_response_body );
149
+
150
+ // fire do_action() so other actors can act on request/response data,
151
+ // primarily used for logging
152
+ $this->broadcast_request();
153
+
154
+ return $this->response;
155
+ }
156
+
157
+ /**
158
+ * Return the parsed response object for the request
159
+ *
160
+ * @since 3.0.0
161
+ * @param string $raw_response_body
162
+ * @return object|API_Request response class instance which implements API_Request
163
+ */
164
+ protected function get_parsed_response( $raw_response_body ) {
165
+
166
+ $handler_class = $this->get_response_handler();
167
+
168
+ return new $handler_class( $raw_response_body );
169
+ }
170
+
171
+ /**
172
+ * Alert other actors that a request has been performed. This is primarily used
173
+ * for request logging.
174
+ *
175
+ * @since 3.0.0
176
+ */
177
+ protected function broadcast_request() {
178
+
179
+ $request_data = array(
180
+ 'method' => $this->get_request_method(),
181
+ 'uri' => $this->get_request_uri(),
182
+ 'user-agent' => $this->get_request_user_agent(),
183
+ 'headers' => $this->get_sanitized_request_headers(),
184
+ 'body' => $this->get_sanitized_request_body(),
185
+ 'duration' => $this->get_request_duration() . 's', // seconds
186
+ );
187
+
188
+ $response_data = array(
189
+ 'code' => $this->get_response_code(),
190
+ 'message' => $this->get_response_message(),
191
+ 'headers' => $this->get_response_headers(),
192
+ 'body' => $this->get_sanitized_response_body() ? $this->get_sanitized_response_body() : $this->get_raw_response_body(),
193
+ );
194
+
195
+ /**
196
+ * API Base Request Performed Action.
197
+ *
198
+ * Fired when an API request is performed via this base class. Plugins can
199
+ * hook into this to log request/response data.
200
+ *
201
+ * @since 3.0.0
202
+ * @param array $request_data {
203
+ * @type string $method request method, e.g. POST
204
+ * @type string $uri request URI
205
+ * @type string $user-agent
206
+ * @type string $headers request headers
207
+ * @type string $body request body
208
+ * @type string $duration in seconds
209
+ * }
210
+ * @param array $response data {
211
+ * @type string $code response HTTP code
212
+ * @type string $message response message
213
+ * @type string $headers response HTTP headers
214
+ * @type string $body response body
215
+ * }
216
+ * @param Base $this instance
217
+ */
218
+ do_action( 'wc_' . $this->get_api_id() . '_api_request_performed', $request_data, $response_data, $this );
219
+ }
220
+
221
+ /**
222
+ * Reset the API response members to their
223
+ *
224
+ * @since 3.0.0
225
+ */
226
+ protected function reset_response() {
227
+
228
+ $this->response_code = null;
229
+ $this->response_message = null;
230
+ $this->response_headers = null;
231
+ $this->raw_response_body = null;
232
+ $this->response = null;
233
+ $this->request_duration = null;
234
+ }
235
+
236
+ /**
237
+ * Get the request URI
238
+ *
239
+ * @since 3.0.0
240
+ * @return string
241
+ */
242
+ protected function get_request_uri() {
243
+
244
+ $uri = $this->request_uri . $this->get_request_path();
245
+
246
+ // append any query params to the URL when necessary
247
+ $query = $this->get_request_query();
248
+ if ( $query ) {
249
+
250
+ $url_parts = parse_url( $uri );
251
+
252
+ // if the URL already has some query params, add to them
253
+ if ( ! empty( $url_parts['query'] ) ) {
254
+ $query = '&' . $query;
255
+ } else {
256
+ $query = '?' . $query;
257
+ }
258
+
259
+ $uri = untrailingslashit( $uri ) . $query;
260
+ }
261
+
262
+ /**
263
+ * Request URI Filter.
264
+ *
265
+ * Allow actors to filter the request URI. Note that child classes can override
266
+ * this method, which means this filter may be invoked prior to the overridden
267
+ * method.
268
+ *
269
+ * @since 3.0.0
270
+ *
271
+ * @param string $uri current request URI
272
+ * @param Base class instance
273
+ */
274
+ return apply_filters( 'wc_' . $this->get_api_id() . '_api_request_uri', $uri, $this );
275
+ }
276
+
277
+ /**
278
+ * Gets the request path.
279
+ *
280
+ * @since 3.0.0
281
+ * @return string
282
+ */
283
+ protected function get_request_path() {
284
+
285
+ return ( $this->get_request() ) ? $this->get_request()->get_path() : '';
286
+ }
287
+
288
+ /**
289
+ * Gets the request URL query.
290
+ *
291
+ * @since 3.0.0
292
+ *
293
+ * @return string
294
+ */
295
+ protected function get_request_query() {
296
+
297
+ $query = '';
298
+ $request = $this->get_request();
299
+
300
+ if ( $request && in_array( strtoupper( $this->get_request_method() ), array( 'GET', 'HEAD' ), true ) ) {
301
+
302
+ $params = $request->get_params();
303
+
304
+ if ( ! empty( $params ) ) {
305
+ $query = http_build_query( $params, '', '&' );
306
+ }
307
+ }
308
+
309
+ return $query;
310
+ }
311
+
312
+ /**
313
+ * Get the request arguments in the format required by wp_remote_request()
314
+ *
315
+ * @since 3.0.0
316
+ *
317
+ * @return array
318
+ */
319
+ protected function get_request_args() {
320
+
321
+ $args = array(
322
+ 'method' => $this->get_request_method(),
323
+ 'timeout' => MINUTE_IN_SECONDS,
324
+ 'redirection' => 0,
325
+ 'httpversion' => $this->get_request_http_version(),
326
+ 'sslverify' => true,
327
+ 'blocking' => true,
328
+ 'user-agent' => $this->get_request_user_agent(),
329
+ 'headers' => $this->get_request_headers(),
330
+ 'body' => $this->get_request_body(),
331
+ 'cookies' => array(),
332
+ );
333
+
334
+ /**
335
+ * Request arguments.
336
+ *
337
+ * Allow other actors to filter the request arguments. Note that
338
+ * child classes can override this method, which means this filter may
339
+ * not be invoked, or may be invoked prior to the overridden method
340
+ *
341
+ * @since 3.0.0
342
+ * @param array $args request arguments
343
+ * @param Base class instance
344
+ */
345
+ return apply_filters( 'wc_' . $this->get_api_id() . '_http_request_args', $args, $this );
346
+ }
347
+
348
+ /**
349
+ * Get the request method, POST by default
350
+ *
351
+ * @since 3.0.0
352
+ * @return string
353
+ */
354
+ protected function get_request_method() {
355
+ // if the request object specifies the method to use, use that, otherwise use the API default
356
+ return $this->get_request() && $this->get_request()->get_method() ? $this->get_request()->get_method() : $this->request_method;
357
+ }
358
+
359
+ /**
360
+ * Gets the request body.
361
+ *
362
+ * @since 3.0.0
363
+ * @return string
364
+ */
365
+ protected function get_request_body() {
366
+
367
+ // GET & HEAD requests don't support a body
368
+ if ( in_array( strtoupper( $this->get_request_method() ), array( 'GET', 'HEAD' ), true ) ) {
369
+ return '';
370
+ }
371
+
372
+ return ( $this->get_request() && $this->get_request()->to_string() ) ? $this->get_request()->to_string() : '';
373
+ }
374
+
375
+ /**
376
+ * Gets the sanitized request body, for logging.
377
+ *
378
+ * @since 3.0.0
379
+ * @return string
380
+ */
381
+ protected function get_sanitized_request_body() {
382
+
383
+ // GET & HEAD requests don't support a body
384
+ if ( in_array( strtoupper( $this->get_request_method() ), array( 'GET', 'HEAD' ), true ) ) {
385
+ return '';
386
+ }
387
+
388
+ return ( $this->get_request() && $this->get_request()->to_string_safe() ) ? $this->get_request()->to_string_safe() : '';
389
+ }
390
+
391
+ /**
392
+ * Get the request HTTP version, 1.1 by default
393
+ *
394
+ * @since 3.0.0
395
+ * @return string
396
+ */
397
+ protected function get_request_http_version() {
398
+
399
+ return $this->request_http_version;
400
+ }
401
+
402
+ /**
403
+ * Get the request headers
404
+ *
405
+ * @since 3.0.0
406
+ * @return array
407
+ */
408
+ protected function get_request_headers() {
409
+ return $this->request_headers;
410
+ }
411
+
412
+ /**
413
+ * Get sanitized request headers suitable for logging, stripped of any
414
+ * confidential information
415
+ *
416
+ * The `Authorization` header is sanitized automatically.
417
+ *
418
+ * Child classes that implement any custom authorization headers should
419
+ * override this method to perform sanitization.
420
+ *
421
+ * @since 3.0.0
422
+ * @return array
423
+ */
424
+ protected function get_sanitized_request_headers() {
425
+
426
+ $headers = $this->get_request_headers();
427
+
428
+ if ( ! empty( $headers['Authorization'] ) ) {
429
+ $headers['Authorization'] = str_repeat( '*', strlen( $headers['Authorization'] ) );
430
+ }
431
+
432
+ return $headers;
433
+ }
434
+
435
+ /**
436
+ * Get the request user agent, defaults to:
437
+ *
438
+ * Dasherized-Plugin-Name/Plugin-Version (WooCommerce/WC-Version; WordPress/WP-Version)
439
+ *
440
+ * @since 3.0.0
441
+ * @return string
442
+ */
443
+ protected function get_request_user_agent() {
444
+
445
+ return sprintf( '%s/%s (WooCommerce/%s; WordPress/%s)', str_replace( ' ', '-', $this->get_plugin()->get_plugin_name() ), $this->get_plugin()->get_version(), WC_VERSION, $GLOBALS['wp_version'] );
446
+ }
447
+
448
+ /**
449
+ * Get the request duration in seconds, rounded to the 5th decimal place
450
+ *
451
+ * @since 3.0.0
452
+ * @return string
453
+ */
454
+ protected function get_request_duration() {
455
+ return $this->request_duration;
456
+ }
457
+
458
+ /**
459
+ * Get the response handler class name
460
+ *
461
+ * @since 3.0.0
462
+ * @return string
463
+ */
464
+ protected function get_response_handler() {
465
+ return $this->response_handler;
466
+ }
467
+
468
+ /**
469
+ * Get the response code
470
+ *
471
+ * @since 3.0.0
472
+ * @return string
473
+ */
474
+ protected function get_response_code() {
475
+ return $this->response_code;
476
+ }
477
+
478
+ /**
479
+ * Get the response message
480
+ *
481
+ * @since 3.0.0
482
+ * @return string
483
+ */
484
+ protected function get_response_message() {
485
+ return $this->response_message;
486
+ }
487
+
488
+ /**
489
+ * Get the response headers
490
+ *
491
+ * @since 3.0.0
492
+ * @return array
493
+ */
494
+ protected function get_response_headers() {
495
+ return $this->response_headers;
496
+ }
497
+
498
+ /**
499
+ * Get the raw response body, prior to any parsing or sanitization
500
+ *
501
+ * @since 3.0.0
502
+ * @return string
503
+ */
504
+ protected function get_raw_response_body() {
505
+ return $this->raw_response_body;
506
+ }
507
+
508
+ /**
509
+ * Get the sanitized response body, provided by the response class
510
+ * to_string_safe() method
511
+ *
512
+ * @since 3.0.0
513
+ * @return string|null
514
+ */
515
+ protected function get_sanitized_response_body() {
516
+ return is_callable( array( $this->get_response(), 'to_string_safe' ) ) ? $this->get_response()->to_string_safe() : null;
517
+ }
518
+
519
+ /**
520
+ * Returns the most recent request object.
521
+ *
522
+ * @since 3.0.0
523
+ *
524
+ * @return API_Request|object the most recent request object
525
+ */
526
+ public function get_request() {
527
+
528
+ return $this->request;
529
+ }
530
+
531
+ /**
532
+ * Returns the most recent response object.
533
+ *
534
+ * @since 3.0.0
535
+ *
536
+ * @return API_Response|object the most recent response object
537
+ */
538
+ public function get_response() {
539
+
540
+ return $this->response;
541
+ }
542
+
543
+ /**
544
+ * Get the ID for the API, used primarily to namespace the action name
545
+ * for broadcasting requests
546
+ *
547
+ * @since 3.0.0
548
+ * @return string
549
+ */
550
+ protected function get_api_id() {
551
+
552
+ return $this->get_plugin()->get_id();
553
+ }
554
+
555
+ /**
556
+ * Return a new request object
557
+ *
558
+ * Child classes must implement this to return an object that implements
559
+ * API_Request which should be used in the child class API methods
560
+ * to build the request. The returned API_Request should be passed
561
+ * to self::perform_request() by your concrete API methods
562
+ *
563
+ * @since 3.0.0
564
+ *
565
+ * @param array $args optional request arguments
566
+ * @return API_Request|object
567
+ */
568
+ abstract protected function get_new_request( $args = array() );
569
+
570
+ /**
571
+ * Return the plugin class instance associated with this API
572
+ *
573
+ * Child classes must implement this to return their plugin class instance
574
+ *
575
+ * This is used for defining the plugin ID used in filter names, as well
576
+ * as the plugin name used for the default user agent.
577
+ *
578
+ * @since 3.0.0
579
+ *
580
+ * @return WooCommerce\Square\Framework\Plugin
581
+ */
582
+ abstract protected function get_plugin();
583
+
584
+ /**
585
+ * Set the response handler class name. This class will be instantiated
586
+ * to parse the response for the request.
587
+ *
588
+ * @since 3.0.0
589
+ *
590
+ * @param string $handler handle class name
591
+ */
592
+ protected function set_response_handler( $handler ) {
593
+ $this->response_handler = $handler;
594
+ }
595
+
596
+ /**
597
+ * Maybe force TLS v1.2 requests.
598
+ *
599
+ * @since 3.0.0
600
+ *
601
+ * @param resource $handle the cURL handle returned by curl_init() (passed by reference)
602
+ * @param array $r the HTTP request arguments
603
+ * @param $url string the request URL
604
+ */
605
+ public function set_tls_1_2_request( $handle, $r, $url ) {
606
+
607
+ if ( ! Square_Helper::str_starts_with( $url, 'https://' ) ) {
608
+ return;
609
+ }
610
+
611
+ curl_setopt( $handle, CURLOPT_SSLVERSION, 6 );
612
+ }
613
+
614
+ /**
615
+ * Determine if TLS v1.2 is required for API requests.
616
+ *
617
+ * Subclasses should override this to return true if TLS v1.2 is required.
618
+ *
619
+ * @since 3.0.0
620
+ * @return bool
621
+ */
622
+ public function require_tls_1_2() {
623
+ return false;
624
+ }
625
+
626
+ /**
627
+ * Determines if TLS 1.2 is available.
628
+ *
629
+ * @since 3.0.0
630
+ *
631
+ * @return bool
632
+ */
633
+ public function is_tls_1_2_available() {
634
+
635
+ // assume availability to avoid notices for unknown SSL types
636
+ $is_available = true;
637
+
638
+ // check the cURL version if installed
639
+ if ( is_callable( 'curl_version' ) ) {
640
+
641
+ $versions = curl_version();
642
+
643
+ // cURL 7.34.0 is considered the minimum version that supports TLS 1.2
644
+ if ( version_compare( $versions['version'], '7.34.0', '<' ) ) {
645
+ $is_available = false;
646
+ }
647
+ }
648
+
649
+ /**
650
+ * Filters whether TLS 1.2 is available.
651
+ *
652
+ * @since 3.0.0
653
+ *
654
+ * @param bool $is_available whether TLS 1.2 is available
655
+ * @param Base $api API class instance
656
+ */
657
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_api_is_tls_1_2_available', $is_available, $this );
658
+ }
659
+ }
includes/Framework/Compatibility/Data_Compatibility.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\Compatibility;
4
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * WooCommerce data compatibility class.
10
+ *
11
+ * @since 3.0.0
12
+ */
13
+ abstract class Data_Compatibility {
14
+
15
+ /**
16
+ * Gets an object property.
17
+ *
18
+ * @since 3.0.0
19
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
20
+ * @param string $prop the property name
21
+ * @param string $context if 'view' then the value will be filtered
22
+ * @param array $compat_props Compatibility properties.
23
+ * @return mixed
24
+ */
25
+ public static function get_prop( $object, $prop, $context = 'edit', $compat_props = array() ) {
26
+
27
+ $value = '';
28
+
29
+ if ( is_callable( array( $object, "get_{$prop}" ) ) ) {
30
+ $value = $object->{"get_{$prop}"}( $context );
31
+ }
32
+
33
+ return $value;
34
+ }
35
+
36
+
37
+ /**
38
+ * Sets an object's properties.
39
+ *
40
+ * Note that this does not save any data to the database.
41
+ *
42
+ * @since 3.0.0
43
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
44
+ * @param array $props the new properties as $key => $value
45
+ * @param array $compat_props Compatibility properties.
46
+ * @return \WC_Data
47
+ */
48
+ public static function set_props( $object, $props, $compat_props = array() ) {
49
+ $object->set_props( $props );
50
+
51
+ return $object;
52
+ }
53
+
54
+
55
+ /**
56
+ * Gets an object's stored meta value.
57
+ *
58
+ * @since 3.0.0
59
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
60
+ * @param string $key the meta key
61
+ * @param bool $single whether to get the meta as a single item. Defaults to `true`
62
+ * @param string $context if 'view' then the value will be filtered
63
+ * @return mixed
64
+ */
65
+ public static function get_meta( $object, $key = '', $single = true, $context = 'edit' ) {
66
+ $value = $object->get_meta( $key, $single, $context );
67
+
68
+ return $value;
69
+ }
70
+
71
+
72
+ /**
73
+ * Stores an object meta value.
74
+ *
75
+ * @since 3.0.0
76
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
77
+ * @param string $key the meta key
78
+ * @param string $value the meta value
79
+ * @param bool $unique Optional. Whether the meta should be unique.
80
+ */
81
+ public static function add_meta_data( $object, $key, $value, $unique = false ) {
82
+ $object->add_meta_data( $key, $value, $unique );
83
+ $object->save_meta_data();
84
+ }
85
+
86
+
87
+ /**
88
+ * Updates an object's stored meta value.
89
+ *
90
+ * @since 3.0.0
91
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
92
+ * @param string $key the meta key
93
+ * @param string $value the meta value
94
+ * @param int|string $meta_id Optional. The specific meta ID to update
95
+ */
96
+ public static function update_meta_data( $object, $key, $value, $meta_id = '' ) {
97
+ $object->update_meta_data( $key, $value, $meta_id );
98
+ $object->save_meta_data();
99
+ }
100
+
101
+
102
+ /**
103
+ * Deletes an object's stored meta value.
104
+ *
105
+ * @since 3.0.0
106
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
107
+ * @param string $key the meta key
108
+ */
109
+ public static function delete_meta_data( $object, $key ) {
110
+ $object->delete_meta_data( $key );
111
+ $object->save_meta_data();
112
+ }
113
+ }
114
+
includes/Framework/Compatibility/Order_Compatibility.php ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\Compatibility;
3
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * WooCommerce order compatibility class.
9
+ *
10
+ * @since 3.0.0
11
+ */
12
+ class Order_Compatibility extends Data_Compatibility {
13
+
14
+ /** @var array mapped compatibility properties, as `$new_prop => $old_prop` */
15
+ protected static $compat_props = array(
16
+ 'date_completed' => 'completed_date',
17
+ 'date_paid' => 'paid_date',
18
+ 'date_modified' => 'modified_date',
19
+ 'date_created' => 'order_date',
20
+ 'customer_id' => 'customer_user',
21
+ 'discount' => 'cart_discount',
22
+ 'discount_tax' => 'cart_discount_tax',
23
+ 'shipping_total' => 'total_shipping',
24
+ 'type' => 'order_type',
25
+ 'currency' => 'order_currency',
26
+ 'version' => 'order_version',
27
+ );
28
+
29
+ /**
30
+ * Gets an order date.
31
+ *
32
+ * This should only be used to retrieve WC core date properties.
33
+ *
34
+ * @since 3.0.0
35
+ *
36
+ * @param \WC_Order $order order object
37
+ * @param string $type type of date to get
38
+ * @param string $context if 'view' then the value will be filtered
39
+ *
40
+ * @return \WC_DateTime|null
41
+ */
42
+ public static function get_date_prop( \WC_Order $order, $type, $context = 'edit' ) {
43
+
44
+ $date = null;
45
+ $prop = "date_{$type}";
46
+ $date = is_callable( array( $order, "get_{$prop}" ) ) ? $order->{"get_{$prop}"}( $context ) : null;
47
+
48
+ return $date;
49
+ }
50
+
51
+
52
+ /**
53
+ * Gets an order property.
54
+ *
55
+ * @since 3.0.0
56
+ * @param \WC_Order $object the order object
57
+ * @param string $prop the property name
58
+ * @param string $context if 'view' then the value will be filtered
59
+ * @return mixed
60
+ */
61
+ public static function get_prop( $object, $prop, $context = 'edit', $compat_props = array() ) {
62
+
63
+ // backport a few specific properties to pre-3.0
64
+ if ( Plugin_Compatibility::is_wc_version_lt_3_0() ) {
65
+
66
+ // convert the shipping_total prop for the edit context
67
+ if ( 'shipping_total' === $prop && 'view' !== $context ) {
68
+
69
+ $prop = 'order_shipping';
70
+
71
+ // get the post_parent and bail early
72
+ } elseif ( 'parent_id' === $prop ) {
73
+
74
+ return $object->post->post_parent;
75
+ }
76
+ }
77
+
78
+ return parent::get_prop( $object, $prop, $context, self::$compat_props );
79
+ }
80
+
81
+
82
+ /**
83
+ * Sets an order's properties.
84
+ *
85
+ * Note that this does not save any data to the database.
86
+ *
87
+ * @since 3.0.0
88
+ * @param \WC_Order $object the order object
89
+ * @param array $props the new properties as $key => $value
90
+ * @return \WC_Data|\WC_Order
91
+ */
92
+ public static function set_props( $object, $props, $compat_props = array() ) {
93
+
94
+ return parent::set_props( $object, $props, self::$compat_props );
95
+ }
96
+
97
+
98
+ /**
99
+ * Order item CRUD compatibility method to add a coupon to an order.
100
+ *
101
+ * @since 3.0.0
102
+ * @param \WC_Order $order the order object
103
+ * @param array $code the coupon code
104
+ * @param int $discount the discount amount.
105
+ * @param int $discount_tax the discount tax amount.
106
+ * @return int the order item ID
107
+ */
108
+ public static function add_coupon( \WC_Order $order, $code = array(), $discount = 0, $discount_tax = 0 ) {
109
+
110
+ $item = new \WC_Order_Item_Coupon();
111
+
112
+ $item->set_props(
113
+ array(
114
+ 'code' => $code,
115
+ 'discount' => $discount,
116
+ 'discount_tax' => $discount_tax,
117
+ 'order_id' => $order->get_id(),
118
+ )
119
+ );
120
+
121
+ $item->save();
122
+ $order->add_item( $item );
123
+
124
+ return $item->get_id();
125
+ }
126
+
127
+
128
+ /**
129
+ * Order item CRUD compatibility method to add a fee to an order.
130
+ *
131
+ * @since 3.0.0
132
+ * @param \WC_Order $order the order object
133
+ * @param object $fee the fee to add
134
+ * @return int the order item ID
135
+ */
136
+ public static function add_fee( \WC_Order $order, $fee ) {
137
+ $item = new \WC_Order_Item_Fee();
138
+
139
+ $item->set_props(
140
+ array(
141
+ 'name' => $fee->name,
142
+ 'tax_class' => $fee->taxable ? $fee->tax_class : 0,
143
+ 'total' => $fee->amount,
144
+ 'total_tax' => $fee->tax,
145
+ 'taxes' => array(
146
+ 'total' => $fee->tax_data,
147
+ ),
148
+ 'order_id' => $order->get_id(),
149
+ )
150
+ );
151
+
152
+ $item->save();
153
+ $order->add_item( $item );
154
+
155
+ return $item->get_id();
156
+ }
157
+
158
+
159
+ /**
160
+ * Order item CRUD compatibility method to add a shipping line to an order.
161
+ *
162
+ * @since 3.0.0
163
+ *
164
+ * @param \WC_Order $order order object
165
+ * @param \WC_Shipping_Rate $shipping_rate shipping rate to add
166
+ * @return int the order item ID
167
+ */
168
+ public static function add_shipping( \WC_Order $order, $shipping_rate ) {
169
+ $item = new \WC_Order_Item_Shipping();
170
+
171
+ $item->set_props(
172
+ array(
173
+ 'method_title' => $shipping_rate->label,
174
+ 'method_id' => $shipping_rate->id,
175
+ 'total' => wc_format_decimal( $shipping_rate->cost ),
176
+ 'taxes' => $shipping_rate->taxes,
177
+ 'order_id' => $order->get_id(),
178
+ )
179
+ );
180
+
181
+ foreach ( $shipping_rate->get_meta_data() as $key => $value ) {
182
+ $item->add_meta_data( $key, $value, true );
183
+ }
184
+
185
+ $item->save();
186
+ $order->add_item( $item );
187
+
188
+ return $item->get_id();
189
+ }
190
+
191
+
192
+ /**
193
+ * Order item CRUD compatibility method to add a tax line to an order.
194
+ *
195
+ * @since 3.0.0
196
+ *
197
+ * @param \WC_Order $order order object
198
+ * @param int $tax_rate_id tax rate ID
199
+ * @param float $tax_amount cart tax amount
200
+ * @param float $shipping_tax_amount shipping tax amount
201
+ * @return int order item ID
202
+ */
203
+ public static function add_tax( \WC_Order $order, $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) {
204
+ $item = new \WC_Order_Item_Tax();
205
+
206
+ $item->set_props(
207
+ array(
208
+ 'rate_id' => $tax_rate_id,
209
+ 'tax_total' => $tax_amount,
210
+ 'shipping_tax_total' => $shipping_tax_amount,
211
+ )
212
+ );
213
+
214
+ $item->set_rate( $tax_rate_id );
215
+ $item->set_order_id( $order->get_id() );
216
+ $item->save();
217
+
218
+ $order->add_item( $item );
219
+
220
+ return $item->get_id();
221
+ }
222
+
223
+ /**
224
+ * Determines if an order has an available shipping address.
225
+ *
226
+ * WooCommerce 3.0+ no longer fills the shipping address with the billing if
227
+ * a shipping address was never set by the customer at checkout, as is the
228
+ * case with virtual orders. This method is helpful for gateways that may
229
+ * reject such transactions with blank shipping information.
230
+ *
231
+ * TODO: Remove when WC 3.0.4 can be required {CW 2017-04-17}
232
+ *
233
+ * @since 3.0.0
234
+ *
235
+ * @param \WC_Order $order order object
236
+ *
237
+ * @return bool
238
+ */
239
+ public static function has_shipping_address( \WC_Order $order ) {
240
+
241
+ return self::get_prop( $order, 'shipping_address_1' ) || self::get_prop( $order, 'shipping_address_2' );
242
+ }
243
+ }
includes/Framework/Lifecycle.php ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework;
4
+
5
+ use WooCommerce;
6
+
7
+ defined( 'ABSPATH' ) or exit;
8
+
9
+ /**
10
+ * Plugin lifecycle handler.
11
+ *
12
+ * Registers and displays milestone notice prompts and eventually the plugin
13
+ * install, upgrade, activation, and deactivation routines.
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Lifecycle {
18
+
19
+
20
+ /** @var array the version numbers that have an upgrade routine */
21
+ protected $upgrade_versions = array();
22
+
23
+ /** @var string minimum milestone version */
24
+ private $milestone_version;
25
+
26
+ /** @var Plugin plugin instance */
27
+ private $plugin;
28
+
29
+
30
+ /**
31
+ * Constructs the class.
32
+ *
33
+ * @since 3.0.0
34
+ *
35
+ * @param Plugin $plugin plugin instance
36
+ */
37
+ public function __construct( WooCommerce\Square\Framework\Plugin $plugin ) {
38
+
39
+ $this->plugin = $plugin;
40
+
41
+ $this->add_hooks();
42
+ }
43
+
44
+
45
+ /**
46
+ * Adds the action & filter hooks.
47
+ *
48
+ * @since 3.0.0
49
+ */
50
+ protected function add_hooks() {
51
+
52
+ // handle activation
53
+ add_action( 'admin_init', array( $this, 'handle_activation' ) );
54
+
55
+ // handle deactivation
56
+ add_action( 'deactivate_' . $this->get_plugin()->get_plugin_file(), array( $this, 'handle_deactivation' ) );
57
+
58
+ if ( is_admin() && ! wp_doing_ajax() ) {
59
+
60
+ // initialize the plugin lifecycle
61
+ add_action( 'wp_loaded', array( $this, 'init' ) );
62
+
63
+ // add the admin notices
64
+ add_action( 'init', array( $this, 'add_admin_notices' ) );
65
+ }
66
+
67
+ // catch any milestones triggered by action
68
+ add_action( 'wc_' . $this->get_plugin()->get_id() . '_milestone_reached', array( $this, 'trigger_milestone' ), 10, 3 );
69
+ }
70
+
71
+
72
+ /**
73
+ * Initializes the plugin lifecycle.
74
+ *
75
+ * @since 3.0.0
76
+ */
77
+ public function init() {
78
+
79
+ // potentially handle a new activation
80
+ $this->handle_activation();
81
+
82
+ $installed_version = $this->get_installed_version();
83
+ $plugin_version = $this->get_plugin()->get_version();
84
+
85
+ // installed version lower than plugin version?
86
+ if ( version_compare( $installed_version, $plugin_version, '<' ) ) {
87
+
88
+ if ( ! $installed_version ) {
89
+
90
+ // store the upgrade event regardless if there was a routine for it
91
+ $this->store_event( 'install' );
92
+
93
+ /**
94
+ * Fires after the plugin has been installed.
95
+ *
96
+ * @since 3.0.0
97
+ */
98
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_installed' );
99
+
100
+ } else {
101
+
102
+ $this->upgrade( $installed_version );
103
+
104
+ // store the upgrade event regardless if there was a routine for it
105
+ $this->add_upgrade_event( $installed_version );
106
+
107
+ // if the plugin never had any previous milestones, consider them all reached so their notices aren't displayed
108
+ if ( ! $this->get_milestone_version() ) {
109
+ $this->set_milestone_version( $plugin_version );
110
+ }
111
+
112
+ /**
113
+ * Fires after the plugin has been updated.
114
+ *
115
+ * @since 3.0.0
116
+ *
117
+ * @param string $installed_version previously installed version
118
+ */
119
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_updated', $installed_version );
120
+ }
121
+
122
+ // new version number
123
+ $this->set_installed_version( $plugin_version );
124
+ }
125
+ }
126
+
127
+
128
+ /**
129
+ * Triggers plugin activation.
130
+ *
131
+ * We don't use register_activation_hook() as that can't be called inside
132
+ * the 'plugins_loaded' action. Instead, we rely on setting to track the
133
+ * plugin's activation status.
134
+ *
135
+ * @internal
136
+ *
137
+ * @link https://developer.wordpress.org/reference/functions/register_activation_hook/#comment-2100
138
+ *
139
+ * @since 3.0.0
140
+ */
141
+ public function handle_activation() {
142
+
143
+ if ( ! get_option( 'wc_' . $this->get_plugin()->get_id() . '_is_active', false ) ) {
144
+
145
+ /**
146
+ * Fires when the plugin is activated.
147
+ *
148
+ * @since 3.0.0
149
+ */
150
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_activated' );
151
+
152
+ update_option( 'wc_' . $this->get_plugin()->get_id() . '_is_active', 'yes' );
153
+ }
154
+ }
155
+
156
+
157
+ /**
158
+ * Triggers plugin deactivation.
159
+ *
160
+ * @internal
161
+ *
162
+ * @since 3.0.0
163
+ */
164
+ public function handle_deactivation() {
165
+
166
+ /**
167
+ * Fires when the plugin is deactivated.
168
+ *
169
+ * @since 3.0.0
170
+ */
171
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_deactivated' );
172
+
173
+ delete_option( 'wc_' . $this->get_plugin()->get_id() . '_is_active' );
174
+ }
175
+
176
+ /**
177
+ * Helper method to install default settings for a plugin.
178
+ *
179
+ * @since 3.0.0
180
+ *
181
+ * @param array $settings settings in format required by WC_Admin_Settings
182
+ */
183
+ public function install_default_settings( array $settings ) {
184
+
185
+ foreach ( $settings as $setting ) {
186
+
187
+ if ( isset( $setting['id'], $setting['default'] ) ) {
188
+ update_option( $setting['id'], $setting['default'] );
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Performs any upgrade tasks based on the provided installed version.
195
+ *
196
+ * @since 3.0.0
197
+ *
198
+ * @param string $installed_version installed version
199
+ */
200
+ protected function upgrade( $installed_version ) {
201
+
202
+ foreach ( $this->upgrade_versions as $upgrade_version ) {
203
+
204
+ $upgrade_method = 'upgrade_to_' . str_replace( array( '.', '-' ), '_', $upgrade_version );
205
+
206
+ if ( version_compare( $installed_version, $upgrade_version, '<' ) && is_callable( array( $this, $upgrade_method ) ) ) {
207
+
208
+ $this->get_plugin()->log( sprintf( "Starting upgrade to v%s", $upgrade_version ) );
209
+
210
+ $this->$upgrade_method( $installed_version );
211
+
212
+ $this->get_plugin()->log( sprintf( "Upgrade to v%s complete.", $upgrade_version ) );
213
+ }
214
+ }
215
+ }
216
+
217
+
218
+ /**
219
+ * Adds any lifecycle admin notices.
220
+ *
221
+ * @since 3.0.0
222
+ */
223
+ public function add_admin_notices() {
224
+
225
+ // display any milestone notices
226
+ foreach ( $this->get_milestone_messages() as $id => $message ) {
227
+
228
+ // bail if this notice was already dismissed
229
+ if ( ! $this->get_plugin()->get_admin_notice_handler()->should_display_notice( $id ) ) {
230
+ continue;
231
+ }
232
+
233
+ /**
234
+ * Filters a milestone notice message.
235
+ *
236
+ * @since 3.0.0
237
+ *
238
+ * @param string $message message text to be used for the milestone notice
239
+ * @param string $id milestone ID
240
+ */
241
+ $message = apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_milestone_message', $this->generate_milestone_notice_message( $message ), $id );
242
+
243
+ if ( $message ) {
244
+
245
+ $this->get_plugin()->get_admin_notice_handler()->add_admin_notice( $message, $id, array(
246
+ 'always_show_on_settings' => false,
247
+ ) );
248
+
249
+ // only display one notice at a time
250
+ break;
251
+ }
252
+ }
253
+ }
254
+
255
+
256
+ /** Milestone Methods *****************************************************/
257
+
258
+
259
+ /**
260
+ * Triggers a milestone.
261
+ *
262
+ * This will only be triggered if the install's "milestone version" is lower
263
+ * than $since. Plugins can specify $since as the version at which a
264
+ * milestone's feature was added. This prevents existing installs from
265
+ * triggering notices for milestones that have long passed, like a payment
266
+ * gateway's first successful payment. Omitting $since will assume the
267
+ * milestone has always existed and should only trigger for fresh installs.
268
+ *
269
+ * @since 3.0.0
270
+ *
271
+ * @param string $id milestone ID
272
+ * @param string $message message to display to the user
273
+ * @param string $since the version since this milestone has existed in the plugin
274
+ * @return bool
275
+ */
276
+ public function trigger_milestone( $id, $message, $since = '1.0.0' ) {
277
+
278
+ // if the plugin was had milestones before this milestone was added, don't trigger it
279
+ if ( version_compare( $this->get_milestone_version(), $since, '>' ) ) {
280
+ return false;
281
+ }
282
+
283
+ return $this->register_milestone_message( $id, $message );
284
+ }
285
+
286
+
287
+ /**
288
+ * Generates a milestone notice message.
289
+ *
290
+ * @since 3.0.0
291
+ *
292
+ * @param string $custom_message custom text that notes what milestone was completed.
293
+ * @return string
294
+ */
295
+ protected function generate_milestone_notice_message( $custom_message ) {
296
+
297
+ $message = '';
298
+
299
+ if ( $this->get_plugin()->get_reviews_url() ) {
300
+
301
+ // to be prepended at random to each milestone notice
302
+ $exclamations = array(
303
+ __( 'Awesome', 'woocommerce-square' ),
304
+ __( 'Fantastic', 'woocommerce-square' ),
305
+ __( 'Cowabunga', 'woocommerce-square' ),
306
+ __( 'Congratulations', 'woocommerce-square' ),
307
+ __( 'Hot dog', 'woocommerce-square' ),
308
+ );
309
+
310
+ $message = $exclamations[ array_rand( $exclamations ) ] . ', ' . esc_html( $custom_message ) . ' ';
311
+
312
+ $message .= sprintf(
313
+ /* translators: Placeholders: %1$s - plugin name, %2$s - <a> tag, %3$s - </a> tag, %4$s - <a> tag, %5$s - </a> tag */
314
+ __( 'Are you having a great experience with %1$s so far? Please consider %2$sleaving a review%3$s! If things aren\'t going quite as expected, we\'re happy to help -- please %4$sreach out to our support team%5$s.', 'woocommerce-square' ),
315
+ '<strong>' . esc_html( $this->get_plugin()->get_plugin_name() ) . '</strong>',
316
+ '<a href="' . esc_url( $this->get_plugin()->get_reviews_url() ) . '">', '</a>',
317
+ '<a href="' . esc_url( $this->get_plugin()->get_support_url() ) . '">', '</a>'
318
+ );
319
+ }
320
+
321
+ return $message;
322
+ }
323
+
324
+
325
+ /**
326
+ * Registers a milestone message to be displayed in the admin.
327
+ *
328
+ * @since 3.0.0
329
+ * @see Lifecycle::generate_milestone_notice_message()
330
+ *
331
+ * @param string $id milestone ID
332
+ * @param string $message message to display to the user
333
+ * @return bool whether the message was successfully registered
334
+ */
335
+ public function register_milestone_message( $id, $message ) {
336
+
337
+ $milestone_messages = $this->get_milestone_messages();
338
+ $dismissed_notices = array_keys( $this->get_plugin()->get_admin_notice_handler()->get_dismissed_notices() );
339
+
340
+ // get the total number of dismissed milestone messages
341
+ $dismissed_milestone_messages = array_intersect( array_keys( $milestone_messages ), $dismissed_notices );
342
+
343
+ // if the user has dismissed more than three milestone messages already, don't add any more
344
+ if ( count( $dismissed_milestone_messages ) > 3 ) {
345
+ return false;
346
+ }
347
+
348
+ $milestone_messages[ $id ] = $message;
349
+
350
+ return update_option( 'wc_' . $this->get_plugin()->get_id() . '_milestone_messages', $milestone_messages );
351
+ }
352
+
353
+
354
+ /** Event history methods *****************************************************************************************/
355
+
356
+
357
+ /**
358
+ * Adds an upgrade lifecycle event.
359
+ *
360
+ * @since 3.0.0
361
+ *
362
+ * @param string $from_version version upgrading from
363
+ * @param array $data extra data to add
364
+ * @return false|int
365
+ */
366
+ public function add_upgrade_event( $from_version, array $data = array() ) {
367
+
368
+ $data = array_merge( array(
369
+ 'from_version' => $from_version,
370
+ ), $data );
371
+
372
+ return $this->store_event( 'upgrade', $data );
373
+ }
374
+
375
+ /**
376
+ * Stores a lifecycle event.
377
+ *
378
+ * This can be used to log installs, upgrades, etc...
379
+ *
380
+ * Uses a direct database query to avoid cache issues.
381
+ *
382
+ * @since 3.0.0
383
+ *
384
+ * @param string $name lifecycle event name
385
+ * @param array $data any extra data to store
386
+ * @return false|int
387
+ */
388
+ public function store_event( $name, array $data = array() ) {
389
+ global $wpdb;
390
+
391
+ $history = $this->get_event_history();
392
+
393
+ $event = array(
394
+ 'name' => wc_clean( $name ),
395
+ 'time' => (int) current_time( 'timestamp' ),
396
+ 'version' => wc_clean( $this->get_plugin()->get_version() ),
397
+ );
398
+
399
+ if ( ! empty( $data ) ) {
400
+ $event['data'] = wc_clean( $data );
401
+ }
402
+
403
+ array_unshift( $history, $event );
404
+
405
+ // limit to the last 30 events
406
+ $history = array_slice( $history, 0, 29 );
407
+
408
+ return $wpdb->replace(
409
+ $wpdb->options,
410
+ array(
411
+ 'option_name' => $this->get_event_history_option_name(),
412
+ 'option_value' => wp_json_encode( $history ),
413
+ 'autoload' => 'no',
414
+ ),
415
+ array(
416
+ '%s',
417
+ '%s',
418
+ )
419
+ );
420
+ }
421
+
422
+
423
+ /**
424
+ * Gets the lifecycle event history.
425
+ *
426
+ * The last 30 events are stored, with the latest first.
427
+ *
428
+ * @since 3.0.0
429
+ *
430
+ * @return array
431
+ */
432
+ public function get_event_history() {
433
+ global $wpdb;
434
+
435
+ $history = array();
436
+
437
+ $results = $wpdb->get_var( $wpdb->prepare( "
438
+ SELECT option_value
439
+ FROM {$wpdb->options}
440
+ WHERE option_name = %s
441
+ ", $this->get_event_history_option_name() ) );
442
+
443
+ if ( $results ) {
444
+ $history = json_decode( $results, true );
445
+ }
446
+
447
+ return is_array( $history ) ? $history : array();
448
+ }
449
+
450
+
451
+ /**
452
+ * Gets the event history option name.
453
+ *
454
+ * @since 3.0.0
455
+ *
456
+ * @return string
457
+ */
458
+ protected function get_event_history_option_name() {
459
+
460
+ return 'wc_' . $this->get_plugin()->get_id() . '_lifecycle_events';
461
+ }
462
+
463
+
464
+ /** Utility Methods *******************************************************/
465
+
466
+
467
+ /**
468
+ * Gets the registered milestone messages.
469
+ *
470
+ * @since 3.0.0
471
+ *
472
+ * @return array
473
+ */
474
+ protected function get_milestone_messages() {
475
+
476
+ return get_option( 'wc_' . $this->get_plugin()->get_id() . '_milestone_messages', array() );
477
+ }
478
+
479
+
480
+ /**
481
+ * Sets the milestone version.
482
+ *
483
+ * @since 3.0.0
484
+ *
485
+ * @param string $version plugin version
486
+ * @return bool
487
+ */
488
+ public function set_milestone_version( $version ) {
489
+
490
+ $this->milestone_version = $version;
491
+
492
+ return update_option( 'wc_' . $this->get_plugin()->get_id() . '_milestone_version', $version );
493
+ }
494
+
495
+
496
+ /**
497
+ * Gets the milestone version.
498
+ *
499
+ * @since 3.0.0
500
+ *
501
+ * @return string
502
+ */
503
+ public function get_milestone_version() {
504
+
505
+ if ( ! $this->milestone_version ) {
506
+ $this->milestone_version = get_option( 'wc_' . $this->get_plugin()->get_id() . '_milestone_version', '' );
507
+ }
508
+
509
+ return $this->milestone_version;
510
+ }
511
+
512
+
513
+ /**
514
+ * Gets the currently installed plugin version.
515
+ *
516
+ * @since 3.0.0
517
+ *
518
+ * @return string
519
+ */
520
+ protected function get_installed_version() {
521
+
522
+ return get_option( $this->get_plugin()->get_plugin_version_name() );
523
+ }
524
+
525
+
526
+ /**
527
+ * Sets the installed plugin version.
528
+ *
529
+ * @since 3.0.0
530
+ *
531
+ * @param string $version version to set
532
+ */
533
+ protected function set_installed_version( $version ) {
534
+
535
+ update_option( $this->get_plugin()->get_plugin_version_name(), $version );
536
+ }
537
+
538
+
539
+ /**
540
+ * Gets the plugin instance.
541
+ *
542
+ * @since 3.0.0
543
+ *
544
+ * @return Plugin
545
+ */
546
+ protected function get_plugin() {
547
+
548
+ return $this->plugin;
549
+ }
550
+ }
includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Order.php ADDED
@@ -0,0 +1,434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Admin;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Plugin;
5
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Plugin;
8
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
9
+
10
+ defined( 'ABSPATH' ) or exit;
11
+
12
+ /**
13
+ * Handle the admin order screens.
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Payment_Gateway_Admin_Order {
18
+
19
+
20
+ /** @var Payment_Gateway_Plugin the plugin instance **/
21
+ protected $plugin;
22
+
23
+
24
+ /**
25
+ * Constructs the class.
26
+ *
27
+ * @since 3.0.0
28
+ *
29
+ * @param Payment_Gateway_Plugin The plugin instance
30
+ */
31
+ public function __construct( Payment_Gateway_Plugin $plugin ) {
32
+
33
+ $this->plugin = $plugin;
34
+
35
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
36
+
37
+ // capture feature
38
+ if ( $this->get_plugin()->supports_capture_charge() ) {
39
+
40
+ add_action( 'woocommerce_order_item_add_action_buttons', array( $this, 'add_capture_button' ) );
41
+
42
+ add_action( 'wp_ajax_wc_' . $this->get_plugin()->get_id() . '_capture_charge', array( $this, 'ajax_process_capture' ) );
43
+
44
+ // bulk capture order action
45
+ add_action( 'admin_footer-edit.php', array( $this, 'maybe_add_capture_charge_bulk_order_action' ) );
46
+ add_action( 'load-edit.php', array( $this, 'process_capture_charge_bulk_order_action' ) );
47
+ }
48
+ }
49
+
50
+
51
+ /**
52
+ * Enqueues the scripts and styles.
53
+ *
54
+ * @internal
55
+ *
56
+ * @since 3.0.0
57
+ *
58
+ * @param string $hook_suffix page hook suffix
59
+ */
60
+ public function enqueue_scripts( $hook_suffix ) {
61
+
62
+ // Order screen assets
63
+ if ( 'shop_order' === get_post_type() ) {
64
+
65
+ // Edit Order screen assets
66
+ if ( 'post.php' === $hook_suffix ) {
67
+
68
+ $order = wc_get_order( Square_Helper::get_request( 'post' ) );
69
+
70
+ if ( ! $order ) {
71
+ return;
72
+ }
73
+
74
+ // bail if the order payment method doesn't belong to this plugin
75
+ if ( ! $this->get_order_gateway( $order ) ) {
76
+ return;
77
+ }
78
+
79
+ $this->enqueue_edit_order_assets( $order );
80
+ }
81
+ }
82
+ }
83
+
84
+
85
+ /**
86
+ * Enqueues the assets for the Edit Order screen.
87
+ *
88
+ * @since 3.0.0
89
+ *
90
+ * @param \WC_Order $order order object
91
+ */
92
+ protected function enqueue_edit_order_assets( \WC_Order $order ) {
93
+
94
+ wp_enqueue_script( 'payment-gateway-admin-order', $this->get_plugin()->get_plugin_url() . '/assets/js/admin/wc-square-payment-gateway-admin-order.min.js', array( 'jquery' ), Plugin::VERSION, true );
95
+
96
+ wp_localize_script( 'payment-gateway-admin-order', 'sv_wc_payment_gateway_admin_order', array(
97
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
98
+ 'gateway_id' => Order_Compatibility::get_prop( $order, 'payment_method' ),
99
+ 'order_id' => Order_Compatibility::get_prop( $order, 'id' ),
100
+ 'capture_ays' => esc_html__( 'Are you sure you wish to process this capture? The action cannot be undone.', 'woocommerce-square' ),
101
+ 'capture_action' => 'wc_' . $this->get_plugin()->get_id() . '_capture_charge',
102
+ 'capture_nonce' => wp_create_nonce( 'wc_' . $this->get_plugin()->get_id() . '_capture_charge' ),
103
+ 'capture_error' => esc_html__( 'Something went wrong, and the capture could no be completed. Please try again.', 'woocommerce-square' ),
104
+ ) );
105
+
106
+ wp_enqueue_style( 'payment-gateway-admin-order', $this->get_plugin()->get_plugin_url() . '/assets/css/admin/wc-square-payment-gateway-admin-order.min.css', Plugin::VERSION );
107
+ }
108
+
109
+
110
+ /** Capture Charge Feature ******************************************************/
111
+
112
+
113
+ /**
114
+ * Adds 'Capture charge' to the Orders screen bulk action select.
115
+ *
116
+ * @since 3.0.0
117
+ */
118
+ public function maybe_add_capture_charge_bulk_order_action() {
119
+ global $post_type, $post_status;
120
+
121
+ if ( ! current_user_can( 'edit_shop_orders' ) ) {
122
+ return;
123
+ }
124
+
125
+ if ( $post_type === 'shop_order' && $post_status !== 'trash' ) {
126
+
127
+ $can_capture_charge = false;
128
+
129
+ // ensure at least one gateway supports capturing charge
130
+ foreach ( $this->get_plugin()->get_gateways() as $gateway ) {
131
+
132
+ // ensure that it supports captures
133
+ if ( $gateway->supports_credit_card_capture() ) {
134
+
135
+ $can_capture_charge = true;
136
+ break;
137
+ }
138
+ }
139
+
140
+ if ( $can_capture_charge ) {
141
+
142
+ ?>
143
+ <script type="text/javascript">
144
+ jQuery( document ).ready( function ( $ ) {
145
+ if ( 0 == $( 'select[name^=action] option[value=wc_capture_charge]' ).size() ) {
146
+ $( 'select[name^=action]' ).append(
147
+ $( '<option>' ).val( '<?php echo esc_js( 'wc_capture_charge' ); ?>' ).text( '<?php esc_html_e( 'Capture Charge', 'woocommerce-square' ); ?>' )
148
+ );
149
+ }
150
+ });
151
+ </script>
152
+ <?php
153
+ }
154
+ }
155
+ }
156
+
157
+
158
+ /**
159
+ * Processes the 'Capture Charge' custom bulk action.
160
+ *
161
+ * @since 3.0.0
162
+ */
163
+ public function process_capture_charge_bulk_order_action() {
164
+ global $typenow;
165
+
166
+ if ( 'shop_order' === $typenow ) {
167
+
168
+ // get the action
169
+ $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
170
+ $action = $wp_list_table->current_action();
171
+
172
+ // bail if not processing a capture
173
+ if ( 'wc_capture_charge' !== $action ) {
174
+ return;
175
+ }
176
+
177
+ if ( ! current_user_can( 'edit_shop_orders' ) ) {
178
+ return;
179
+ }
180
+
181
+ // security check
182
+ check_admin_referer( 'bulk-posts' );
183
+
184
+ // make sure order IDs are submitted
185
+ if ( isset( $_REQUEST['post'] ) ) {
186
+ $order_ids = array_map( 'absint', $_REQUEST['post'] );
187
+ }
188
+
189
+ // return if there are no orders to export
190
+ if ( empty( $order_ids ) ) {
191
+ return;
192
+ }
193
+
194
+ // give ourselves an unlimited timeout if possible
195
+ @set_time_limit( 0 );
196
+
197
+ foreach ( $order_ids as $order_id ) {
198
+
199
+ $order = wc_get_order( $order_id );
200
+
201
+ if ( $order && ( $gateway = $this->get_order_gateway( $order ) ) ) {
202
+ $gateway->get_capture_handler()->maybe_perform_capture( $order );
203
+ }
204
+ }
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Adds the capture charge button to the order UI.
210
+ *
211
+ * @internal
212
+ *
213
+ * @since 3.0.0
214
+ *
215
+ * @param \WC_Order $order order object
216
+ */
217
+ public function add_capture_button( $order ) {
218
+
219
+ // only display the button for core orders
220
+ if ( ! $order instanceof \WC_Order || 'shop_order' !== get_post_type( Order_Compatibility::get_prop( $order, 'id' ) ) ) {
221
+ return;
222
+ }
223
+
224
+ $gateway = $this->get_order_gateway( $order );
225
+
226
+ if ( ! $gateway ) {
227
+ return;
228
+ }
229
+
230
+ if ( ! $gateway->get_capture_handler()->is_order_ready_for_capture( $order ) ) {
231
+ return;
232
+ }
233
+
234
+ $tooltip = '';
235
+ $classes = array(
236
+ 'button',
237
+ 'wc-square-payment-gateway-capture',
238
+ 'wc-' . $gateway->get_id_dasherized() . '-capture',
239
+ );
240
+
241
+ // indicate if the partial-capture UI can be shown
242
+ if ( $gateway->supports_credit_card_partial_capture() && $gateway->is_partial_capture_enabled() ) {
243
+ $classes[] = 'partial-capture';
244
+ } elseif ( $gateway->get_capture_handler()->order_can_be_captured( $order ) ) {
245
+ $classes[] = 'button-primary';
246
+ }
247
+
248
+ // ensure that the authorization is still valid for capture
249
+ if ( ! $gateway->get_capture_handler()->order_can_be_captured( $order ) ) {
250
+
251
+ $classes[] = 'tips disabled';
252
+
253
+ // add some tooltip wording explaining why this cannot be captured
254
+ if ( $gateway->get_capture_handler()->is_order_fully_captured( $order ) ) {
255
+ $tooltip = esc_html__( 'This charge has been fully captured.', 'woocommerce-square' );
256
+ } elseif ( $gateway->get_order_meta( $order, 'trans_date' ) && $gateway->get_capture_handler()->has_order_authorization_expired( $order ) ) {
257
+ $tooltip = esc_html__( 'This charge can no longer be captured.', 'woocommerce-square' );
258
+ } else {
259
+ $tooltip = esc_html__( 'This charge cannot be captured.', 'woocommerce-square' );
260
+ }
261
+ }
262
+
263
+ ?>
264
+
265
+ <button type="button" class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>" <?php echo ( $tooltip ) ? 'data-tip="' . esc_html( $tooltip ) . '"' : ''; ?>><?php esc_html_e( 'Capture Charge', 'woocommerce-square' ); ?></button>
266
+
267
+ <?php
268
+
269
+ // add the partial capture UI HTML
270
+ if ( $gateway->supports_credit_card_partial_capture() && $gateway->is_partial_capture_enabled() ) {
271
+ $this->output_partial_capture_html( $order, $gateway );
272
+ }
273
+ }
274
+
275
+
276
+ /**
277
+ * Outputs the partial capture UI HTML.
278
+ *
279
+ * @since 3.0.0
280
+ *
281
+ * @param \WC_Order $order order object
282
+ * @param Payment_Gateway $gateway gateway instance
283
+ */
284
+ protected function output_partial_capture_html( \WC_Order $order, Payment_Gateway $gateway ) {
285
+
286
+ $authorization_total = $gateway->get_capture_handler()->get_order_authorization_amount( $order );
287
+ $total_captured = $gateway->get_order_meta( $order, 'capture_total' );
288
+ $remaining_total = Square_Helper::number_format( (float) $order->get_total() - (float) $total_captured );
289
+
290
+ include( $this->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-order-partial-capture.php' );
291
+ }
292
+
293
+
294
+ /**
295
+ * Processes a capture via AJAX.
296
+ *
297
+ * @internal
298
+ *
299
+ * @since 3.0.0
300
+ */
301
+ public function ajax_process_capture() {
302
+
303
+ check_ajax_referer( 'wc_' . $this->get_plugin()->get_id() . '_capture_charge', 'nonce' );
304
+
305
+ $gateway_id = Square_Helper::get_request( 'gateway_id' );
306
+
307
+ if ( ! $this->get_plugin()->has_gateway( $gateway_id ) ) {
308
+ die();
309
+ }
310
+
311
+ $gateway = $this->get_plugin()->get_gateway( $gateway_id );
312
+
313
+ try {
314
+
315
+ $order_id = Square_Helper::get_request( 'order_id' );
316
+ $order = wc_get_order( $order_id );
317
+
318
+ if ( ! $order ) {
319
+ throw new \Exception( 'Invalid order ID' );
320
+ }
321
+
322
+ if ( ! current_user_can( 'edit_shop_order', $order_id ) ) {
323
+ throw new \Exception( 'Invalid permissions' );
324
+ }
325
+
326
+ if ( Order_Compatibility::get_prop( $order, 'payment_method' ) !== $gateway->get_id() ) {
327
+ throw new \Exception( 'Invalid payment method' );
328
+ }
329
+
330
+ $amount_captured = (float) $gateway->get_order_meta( $order, 'capture_total' );
331
+
332
+ if ( Square_Helper::get_request( 'amount' ) ) {
333
+ $amount = (float) Square_Helper::get_request( 'amount' );
334
+ } else {
335
+ $amount = $order->get_total();
336
+ }
337
+
338
+ $result = $gateway->get_capture_handler()->perform_capture( $order, $amount );
339
+
340
+ if ( empty( $result['success'] ) ) {
341
+ throw new \Exception( $result['message'] );
342
+ }
343
+
344
+ wp_send_json_success( array(
345
+ 'message' => html_entity_decode( wp_strip_all_tags( $result['message'] ) ), // ensure any HTML tags are removed and the currency symbol entity is decoded
346
+ ) );
347
+
348
+ } catch ( \Exception $e ) {
349
+
350
+ wp_send_json_error( array(
351
+ 'message' => $e->getMessage(),
352
+ ) );
353
+ }
354
+ }
355
+
356
+
357
+ /**
358
+ * Gets the gateway object from an order.
359
+ *
360
+ * @since 3.0.0
361
+ *
362
+ * @param \WC_Order $order order object
363
+ * @return Payment_Gateway
364
+ */
365
+ protected function get_order_gateway( \WC_Order $order ) {
366
+
367
+ $capture_gateway = null;
368
+
369
+ $payment_method = Order_Compatibility::get_prop( $order, 'payment_method' );
370
+
371
+ if ( $this->get_plugin()->has_gateway( $payment_method ) ) {
372
+
373
+ $gateway = $this->get_plugin()->get_gateway( $payment_method );
374
+
375
+ // ensure that it supports captures
376
+ if ( $gateway->supports_credit_card_capture() ) {
377
+ $capture_gateway = $gateway;
378
+ }
379
+ }
380
+
381
+ return $capture_gateway;
382
+ }
383
+
384
+
385
+ /**
386
+ * Gets the plugin instance.
387
+ *
388
+ * @since 3.0.0
389
+ *
390
+ * @return Payment_Gateway_Plugin the plugin instance
391
+ */
392
+ protected function get_plugin() {
393
+
394
+ return $this->plugin;
395
+ }
396
+
397
+ /**
398
+ * Captures an order on status change to a "paid" status.
399
+ *
400
+ * @internal
401
+ *
402
+ * @since 3.0.0
403
+ *
404
+ * @param int $order_id order ID
405
+ * @param string $old_status status being changed
406
+ * @param string $new_status new order status
407
+ */
408
+ public function maybe_capture_paid_order( $order_id, $old_status, $new_status ) {
409
+
410
+ wc_deprecated_function( __METHOD__, '3.0.0' );
411
+ }
412
+
413
+
414
+ /**
415
+ * Determines if an order is ready for capture.
416
+ *
417
+ * @since 3.0.0
418
+ *
419
+ * @param \WC_Order $order order object
420
+ * @return bool
421
+ */
422
+ protected function is_order_ready_for_capture( \WC_Order $order ) {
423
+
424
+ wc_deprecated_function( __METHOD__, '3.0.0' );
425
+
426
+ $gateway = $this->get_order_gateway( $order );
427
+
428
+ if ( ! $gateway ) {
429
+ return false;
430
+ }
431
+
432
+ return $gateway->get_capture_handler()->is_order_ready_for_capture( $order );
433
+ }
434
+ }
includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_Payment_Token_Editor.php ADDED
@@ -0,0 +1,668 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Admin;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Direct;
5
+ use WooCommerce\Square\Plugin;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
8
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Token;
9
+
10
+ defined( 'ABSPATH' ) or exit;
11
+
12
+ /**
13
+ * The token editor.
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Payment_Gateway_Admin_Payment_Token_Editor {
18
+
19
+
20
+ /** @var Payment_Gateway_Direct the gateway object **/
21
+ protected $gateway;
22
+
23
+
24
+ /**
25
+ * Constructs the editor.
26
+ *
27
+ * @since 3.0.0
28
+ *
29
+ * @param Payment_Gateway_Direct the gateway object
30
+ */
31
+ public function __construct( Payment_Gateway_Direct $gateway ) {
32
+
33
+ $this->gateway = $gateway;
34
+
35
+ // Load the editor scripts and styles
36
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) );
37
+
38
+ // Display the tokens markup inside the editor
39
+ add_action( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_tokens', array( $this, 'display_tokens' ) );
40
+
41
+ /** AJAX actions **/
42
+
43
+ // Get the blank token markup via AJAX
44
+ add_action( 'wp_ajax_wc_payment_gateway_' . $this->get_gateway()->get_id() . '_admin_get_blank_payment_token', array( $this, 'ajax_get_blank_token' ) );
45
+
46
+ // Remove a token via AJAX
47
+ add_action( 'wp_ajax_wc_payment_gateway_' . $this->get_gateway()->get_id() . '_admin_remove_payment_token', array( $this, 'ajax_remove_token' ) );
48
+
49
+ // Refresh the tokens via AJAX
50
+ add_action( 'wp_ajax_wc_payment_gateway_' . $this->get_gateway()->get_id() . '_admin_refresh_payment_tokens', array( $this, 'ajax_refresh_tokens' ) );
51
+ }
52
+
53
+
54
+ /**
55
+ * Load the editor scripts and styles.
56
+ *
57
+ * @since 3.0.0
58
+ */
59
+ public function enqueue_scripts_styles() {
60
+
61
+ // Stylesheet
62
+ wp_enqueue_style( 'payment-gateway-token-editor', $this->get_gateway()->get_plugin()->get_plugin_url() . '/assets/css/admin/wc-square-payment-gateway-token-editor.min.css', array(), Plugin::VERSION );
63
+
64
+ // Main editor script
65
+ wp_enqueue_script( 'payment-gateway-token-editor', $this->get_gateway()->get_plugin()->get_plugin_url() . '/assets/js/admin/wc-square-payment-gateway-token-editor.min.js', array( 'jquery' ), Plugin::VERSION, true );
66
+
67
+ wp_localize_script( 'payment-gateway-token-editor', 'wc_payment_gateway_token_editor', array(
68
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
69
+ 'actions' => array(
70
+ 'remove_token' => array(
71
+ 'ays' => esc_html__( 'Are you sure you want to remove this token?', 'woocommerce-square' ),
72
+ 'nonce' => wp_create_nonce( 'wc_payment_gateway_admin_remove_payment_token' ),
73
+ ),
74
+ 'add_token' => array(
75
+ 'nonce' => wp_create_nonce( 'wc_payment_gateway_admin_get_blank_payment_token' ),
76
+ ),
77
+ 'refresh' => array(
78
+ 'nonce' => wp_create_nonce( 'wc_payment_gateway_admin_refresh_payment_tokens' ),
79
+ ),
80
+ 'save' => array(
81
+ 'error' => esc_html__( 'Invalid token data', 'woocommerce-square' ),
82
+ ),
83
+ ),
84
+ 'i18n' => array(
85
+ 'general_error' => esc_html__( 'An error occurred. Please try again.', 'woocommerce-square' ),
86
+ ),
87
+ ) );
88
+ }
89
+
90
+
91
+ /**
92
+ * Display the token editor.
93
+ *
94
+ * @since 3.0.0
95
+ * @param int $user_id the user ID
96
+ */
97
+ public function display( $user_id ) {
98
+
99
+ $id = $this->get_gateway()->get_id();
100
+ $title = $this->get_title();
101
+ $columns = $this->get_columns();
102
+ $actions = $this->get_actions();
103
+
104
+ include( $this->get_gateway()->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-user-payment-token-editor.php' );
105
+ }
106
+
107
+
108
+ /**
109
+ * Display the tokens.
110
+ *
111
+ * @since 3.0.0
112
+ * @param int $user_id the user ID
113
+ */
114
+ public function display_tokens( $user_id ) {
115
+
116
+ $tokens = $this->get_tokens( $user_id );
117
+
118
+ $fields = $this->get_fields();
119
+ $input_name = $this->get_input_name();
120
+ $actions = $this->get_token_actions();
121
+ $type = $this->get_payment_type();
122
+
123
+ $index = 0;
124
+
125
+ foreach ( $tokens as $token ) {
126
+
127
+ include( $this->get_gateway()->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-user-payment-token-editor-token.php' );
128
+
129
+ $index++;
130
+ }
131
+ }
132
+
133
+
134
+ /**
135
+ * Save the token editor.
136
+ *
137
+ * @since 3.0.0
138
+ * @param int $user_id the user ID
139
+ */
140
+ public function save( $user_id ) {
141
+
142
+ $tokens = ( isset( $_POST[ $this->get_input_name() ] ) ) ? $_POST[ $this->get_input_name() ] : array();
143
+
144
+ $built_tokens = array();
145
+
146
+ foreach ( $tokens as $data ) {
147
+
148
+ $token_id = $data['id'];
149
+
150
+ unset( $data['id'] );
151
+
152
+ if ( ! $token_id ) {
153
+ continue;
154
+ }
155
+
156
+ if ( 'credit_card' === $data['type'] ) {
157
+ $data = $this->prepare_expiry_date( $data );
158
+ }
159
+
160
+ // Set the default method
161
+ $data['default'] = $token_id === Square_Helper::get_post( $this->get_input_name() . '_default' );
162
+
163
+ if ( $data = $this->validate_token_data( $token_id, $data ) ) {
164
+ $built_tokens[ $token_id ] = $this->build_token( $user_id, $token_id, $data );
165
+ }
166
+ }
167
+
168
+ $this->update_tokens( $user_id, $built_tokens );
169
+ }
170
+
171
+
172
+ /**
173
+ * Add a token via AJAX.
174
+ *
175
+ * @since 3.0.0
176
+ */
177
+ public function ajax_get_blank_token() {
178
+
179
+ check_ajax_referer( 'wc_payment_gateway_admin_get_blank_payment_token', 'security' );
180
+
181
+ $index = Square_Helper::get_request( 'index' );
182
+
183
+ if ( $index ) {
184
+
185
+ $fields = $this->get_fields();
186
+ $input_name = $this->get_input_name();
187
+ $actions = $this->get_token_actions();
188
+ $type = $this->get_payment_type();
189
+ $user_id = 0;
190
+
191
+ $token = array_fill_keys( array_keys( $fields ), '' );
192
+ $token['id'] = '';
193
+ $token['expiry'] = '';
194
+ $token['default'] = false;
195
+
196
+ ob_start();
197
+
198
+ include( $this->get_gateway()->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-user-payment-token-editor-token.php' );
199
+
200
+ $html = ob_get_clean();
201
+
202
+ wp_send_json_success( $html );
203
+
204
+ } else {
205
+
206
+ wp_send_json_error();
207
+ }
208
+ }
209
+
210
+
211
+ /**
212
+ * Remove a token via AJAX.
213
+ *
214
+ * @since 3.0.0
215
+ */
216
+ public function ajax_remove_token() {
217
+
218
+ try {
219
+
220
+ if ( ! check_ajax_referer( 'wc_payment_gateway_admin_remove_payment_token', 'security' ) ) {
221
+ throw new \Exception( 'Invalid nonce' );
222
+ }
223
+
224
+ $user_id = Square_Helper::get_request( 'user_id' );
225
+ $token_id = Square_Helper::get_request( 'token_id' );
226
+
227
+ if ( ! $user_id ) {
228
+ throw new \Exception( 'User ID is missing' );
229
+ }
230
+
231
+ if ( ! $token_id ) {
232
+ throw new \Exception( 'Token ID is missing' );
233
+ }
234
+
235
+ if ( $this->remove_token( $user_id, $token_id ) ) {
236
+ wp_send_json_success();
237
+ } else {
238
+ throw new \Exception( 'Could not remove token' );
239
+ }
240
+
241
+ } catch ( \Exception $e ) {
242
+
243
+ wp_send_json_error( $e->getMessage() );
244
+ }
245
+ }
246
+
247
+
248
+ /**
249
+ * Refresh the tokens list via AJAX.
250
+ *
251
+ * @since 3.0.0
252
+ */
253
+ public function ajax_refresh_tokens() {
254
+
255
+ try {
256
+
257
+ if ( ! check_ajax_referer( 'wc_payment_gateway_admin_refresh_payment_tokens', 'security', false ) ) {
258
+ throw new \Exception( 'Invalid nonce' );
259
+ }
260
+
261
+ $user_id = Square_Helper::get_request( 'user_id' );
262
+
263
+ if ( ! $user_id ) {
264
+ throw new \Exception( 'User ID is missing' );
265
+ }
266
+
267
+ ob_start();
268
+
269
+ $this->display_tokens( $user_id );
270
+
271
+ $html = ob_get_clean();
272
+
273
+ wp_send_json_success( trim( $html ) );
274
+
275
+ } catch ( \Exception $e ) {
276
+
277
+ wp_send_json_error( $e->getMessage() );
278
+ }
279
+ }
280
+
281
+
282
+ /**
283
+ * Build a token object from data saved in the admin.
284
+ *
285
+ * This method allows concrete gateways to add special token data.
286
+ * See Authorize.net CIM for an example.
287
+ *
288
+ * @since 3.0.0
289
+ *
290
+ * @param int $user_id the user ID
291
+ * @param string $token_id the token ID
292
+ * @param array $data the token data
293
+ * @return Payment_Gateway_Payment_Token the payment token object
294
+ */
295
+ protected function build_token( $user_id, $token_id, $data ) {
296
+ return $this->get_gateway()->get_payment_tokens_handler()->build_token( $token_id, $data );
297
+ }
298
+
299
+
300
+ /**
301
+ * Update the user's token data.
302
+ *
303
+ * @since 3.0.0
304
+ * @param int $user_id the user ID
305
+ * @param array the token objects
306
+ */
307
+ protected function update_tokens( $user_id, $tokens ) {
308
+
309
+ $this->get_gateway()->get_payment_tokens_handler()->update_tokens( $user_id, $tokens, $this->get_gateway()->get_environment() );
310
+ }
311
+
312
+
313
+ /**
314
+ * Remove a specific token.
315
+ *
316
+ * @since 3.0.0
317
+ * @param int $user_id the user ID
318
+ * @param string $token_id the token ID
319
+ * @return bool whether the token was successfully removed
320
+ */
321
+ protected function remove_token( $user_id, $token_id ) {
322
+
323
+ return $this->get_gateway()->get_payment_tokens_handler()->remove_token( $user_id, $token_id, $this->get_gateway()->get_environment() );
324
+ }
325
+
326
+
327
+ /**
328
+ * Validate a token's data before saving.
329
+ *
330
+ * Concrete gateways can override this to provide their own validation.
331
+ *
332
+ * @since 3.0.0
333
+ * @param array $data the token data
334
+ * @return array|bool the validated token data or false if the token should not be saved
335
+ */
336
+ protected function validate_token_data( $token_id, $data ) {
337
+
338
+ /**
339
+ * Filter the validated token data.
340
+ *
341
+ * @since 3.0.0
342
+ * @param array $data the validated token data
343
+ * @param string $token_id the token ID
344
+ * @param Payment_Gateway_Admin_Payment_Token_Editor the token editor instance
345
+ * @return array the validated token data
346
+ */
347
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_validate_token_data', $data, $token_id, $this );
348
+ }
349
+
350
+
351
+ /**
352
+ * Correctly format a credit card expiration date for storage.
353
+ *
354
+ * @since 3.0.0
355
+ * @param array $data
356
+ * @return array
357
+ */
358
+ protected function prepare_expiry_date( $data ) {
359
+
360
+ // expiry date must be present, include a forward slash and be 5 characters (MM/YY)
361
+ if ( ! $data['expiry'] || ! Square_Helper::str_exists( $data['expiry'], '/' ) || 5 !== strlen( $data['expiry'] ) ) {
362
+ unset( $data['expiry'] );
363
+ return $data;
364
+ }
365
+
366
+ list( $data['exp_month'], $data['exp_year'] ) = explode( '/', $data['expiry'] );
367
+
368
+ unset( $data['expiry'] );
369
+
370
+ return $data;
371
+ }
372
+
373
+
374
+ /**
375
+ * Get the stored tokens for a user.
376
+ *
377
+ * @since 3.0.0
378
+ * @param int $user_id the user ID
379
+ * @return array the tokens in db format
380
+ */
381
+ protected function get_tokens( $user_id ) {
382
+
383
+ // Clear any cached tokens
384
+ $this->get_gateway()->get_payment_tokens_handler()->clear_transient( $user_id );
385
+
386
+ // get the customer ID separately so it's never auto-created from the admin
387
+ $customer_id = $this->get_gateway()->get_customer_id( $user_id, array(
388
+ 'autocreate' => false,
389
+ ) );
390
+
391
+ $stored_tokens = $this->get_gateway()->get_payment_tokens_handler()->get_tokens( $user_id, array(
392
+ 'customer_id' => $customer_id,
393
+ ) );
394
+
395
+ $tokens = array();
396
+
397
+ foreach( $stored_tokens as $token ) {
398
+
399
+ $token_id = $token->get_id();
400
+
401
+ // Set the token data
402
+ $tokens[ $token_id ] = $token->to_datastore_format();
403
+
404
+ $tokens[ $token_id ]['id'] = $token_id;
405
+
406
+ // Set the credit card expiration date
407
+ if ( $token->is_credit_card() ) {
408
+ $tokens[ $token_id ]['expiry'] = $token->get_exp_month() && $token->get_exp_year() ? $token->get_exp_date() : '';
409
+ }
410
+
411
+ $tokens[ $token_id ]['default'] = $token->is_default();
412
+
413
+ // Parse against the editor field IDs so we don't have to isset throughout the HTML
414
+ $tokens[ $token_id ] = wp_parse_args( $tokens[ $token_id ], array_fill_keys( array_keys( $this->get_fields() ), '' ) );
415
+ }
416
+
417
+ return $tokens;
418
+ }
419
+
420
+
421
+ /**
422
+ * Get the editor title.
423
+ *
424
+ * @since 3.0.0
425
+ * @return string
426
+ */
427
+ protected function get_title() {
428
+
429
+ $title = $this->get_gateway()->get_title();
430
+
431
+ // Append the environment name if there are multiple
432
+ if ( $this->get_gateway()->get_plugin()->get_admin_user_handler()->has_multiple_environments() ) {
433
+ $title .= ' ' . sprintf( esc_html__( '(%s)', 'woocommerce-square' ), $this->get_gateway()->get_environment_name() );
434
+ }
435
+
436
+ /**
437
+ * Filters the token editor name.
438
+ *
439
+ * @since 3.0.0
440
+ *
441
+ * @param string $title the editor title
442
+ * @param Payment_Gateway_Admin_Payment_Token_Editor $editor the editor object
443
+ */
444
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_title', $title, $this );
445
+ }
446
+
447
+
448
+ /**
449
+ * Get the editor columns.
450
+ *
451
+ * @since 3.0.0
452
+ * @return array
453
+ */
454
+ protected function get_columns() {
455
+
456
+ $fields = $this->get_fields();
457
+ $columns = array();
458
+
459
+ foreach ( $fields as $field_id => $field ) {
460
+ $columns[ $field_id ] = isset( $field['label'] ) ? $field['label'] : '';
461
+ }
462
+
463
+ $columns['default'] = esc_html__( 'Default', 'woocommerce-square' );
464
+ $columns['actions'] = '';
465
+
466
+ /**
467
+ * Filters the admin token editor columns.
468
+ *
469
+ * @since 3.0.0
470
+ *
471
+ * @param array $columns
472
+ * @param Payment_Gateway_Admin_Payment_Token_Editor $editor the editor object
473
+ */
474
+ $columns = apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_columns', $columns, $this );
475
+
476
+ return $columns;
477
+ }
478
+
479
+
480
+ /**
481
+ * Get the editor fields.
482
+ *
483
+ * @since 3.0.0
484
+ * @return array
485
+ */
486
+ protected function get_fields( $type = '' ) {
487
+
488
+ if ( ! $type ) {
489
+ $type = $this->get_gateway()->get_payment_type();
490
+ }
491
+
492
+ switch ( $type ) {
493
+
494
+ case 'credit-card' :
495
+
496
+ // Define the credit card fields
497
+ $fields = array(
498
+ 'id' => array(
499
+ 'label' => esc_html__( 'Token ID', 'woocommerce-square' ),
500
+ 'editable' => ! $this->get_gateway()->get_api()->supports_get_tokenized_payment_methods(),
501
+ 'required' => true,
502
+ ),
503
+ 'card_type' => array(
504
+ 'label' => esc_html__( 'Card Type', 'woocommerce-square' ),
505
+ 'type' => 'select',
506
+ 'options' => $this->get_card_type_options(),
507
+ ),
508
+ 'last_four' => array(
509
+ 'label' => esc_html__( 'Last Four', 'woocommerce-square' ),
510
+ 'attributes' => array(
511
+ 'pattern' => '[0-9]{4}',
512
+ 'maxlength' => 4,
513
+ ),
514
+ ),
515
+ 'expiry' => array(
516
+ 'label' => esc_html__( 'Expiration (MM/YY)', 'woocommerce-square' ),
517
+ 'attributes' => array(
518
+ 'placeholder' => 'MM/YY',
519
+ 'pattern' => '(0[1-9]|1[012])[- /.]\d\d',
520
+ 'maxlength' => 5,
521
+ ),
522
+ ),
523
+ );
524
+
525
+ break;
526
+
527
+ default :
528
+ $fields = array();
529
+ }
530
+
531
+ // Parse each field against the defaults
532
+ foreach ( $fields as $field_id => $field ) {
533
+
534
+ $fields[ $field_id ] = wp_parse_args( $field, array(
535
+ 'label' => '',
536
+ 'type' => 'text',
537
+ 'attributes' => array(),
538
+ 'editable' => true,
539
+ 'required' => false,
540
+ ) );
541
+ }
542
+
543
+ /**
544
+ * Filters the admin token editor fields.
545
+ *
546
+ * @since 3.0.0
547
+ *
548
+ * @param array $fields
549
+ * @param Payment_Gateway_Admin_Payment_Token_Editor $editor the editor object
550
+ */
551
+ $fields = apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_fields', $fields, $this );
552
+
553
+ return $fields;
554
+ }
555
+
556
+
557
+ /**
558
+ * Get the token payment type.
559
+ *
560
+ * @since 3.0.0
561
+ * @return string
562
+ */
563
+ protected function get_payment_type() {
564
+
565
+ return str_replace( '-', '_', $this->get_gateway()->get_payment_type() );
566
+ }
567
+
568
+
569
+ /**
570
+ * Get the credit card type field options.
571
+ *
572
+ * @since 3.0.0
573
+ * @return array
574
+ */
575
+ protected function get_card_type_options() {
576
+
577
+ $card_types = $this->get_gateway()->get_card_types();
578
+ $options = array();
579
+
580
+ foreach ( $card_types as $card_type ) {
581
+
582
+ $card_type = Payment_Gateway_Helper::normalize_card_type( $card_type );
583
+
584
+ $options[ $card_type ] = Payment_Gateway_Helper::payment_type_to_name( $card_type );
585
+ }
586
+
587
+ return $options;
588
+ }
589
+
590
+
591
+ /**
592
+ * Get the HTML name for the token fields.
593
+ *
594
+ * @since 3.0.0
595
+ * @return string
596
+ */
597
+ protected function get_input_name() {
598
+
599
+ return 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokens';
600
+ }
601
+
602
+
603
+ /**
604
+ * Get the available editor actions.
605
+ *
606
+ * @since 3.0.0
607
+ * @return array
608
+ */
609
+ protected function get_actions() {
610
+
611
+ $actions = array();
612
+
613
+ if ( $this->get_gateway()->get_api()->supports_get_tokenized_payment_methods() ) {
614
+ $actions['refresh'] = esc_html__( 'Refresh', 'woocommerce-square' );
615
+ } else {
616
+ $actions['add-new'] = esc_html__( 'Add New', 'woocommerce-square' );
617
+ }
618
+
619
+ $actions['save'] = esc_html__( 'Save', 'woocommerce-square' );
620
+
621
+ /**
622
+ * Filters the payment token editor actions.
623
+ *
624
+ * @since 3.0.0
625
+ *
626
+ * @param array $actions the actions
627
+ * @param Payment_Gateway_Admin_Payment_Token_Editor $editor the editor object
628
+ */
629
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_actions', $actions, $this );
630
+ }
631
+
632
+
633
+ /**
634
+ * Get the available token actions.
635
+ *
636
+ * @since 3.0.0
637
+ * @return array
638
+ */
639
+ protected function get_token_actions() {
640
+
641
+ $actions = array(
642
+ 'remove' => esc_html__( 'Remove', 'woocommerce-square' ),
643
+ );
644
+
645
+ /**
646
+ * Filters the token actions.
647
+ *
648
+ * @since 3.0.0
649
+ *
650
+ * @param array $actions the token actions
651
+ * @param Payment_Gateway_Admin_Payment_Token_Editor $editor the editor object
652
+ */
653
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_token_editor_token_actions', $actions, $this );
654
+ }
655
+
656
+
657
+ /**
658
+ * Gets the gateway object.
659
+ *
660
+ * @since 3.0.0
661
+ *
662
+ * @return Payment_Gateway_Direct the gateway object
663
+ */
664
+ protected function get_gateway() {
665
+
666
+ return $this->gateway;
667
+ }
668
+ }
includes/Framework/PaymentGateway/Admin/Payment_Gateway_Admin_User_Handler.php ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Admin;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Plugin;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * Handle the admin user profile settings.
10
+ *
11
+ * @since 3.0.0
12
+ */
13
+ class Payment_Gateway_Admin_User_Handler {
14
+
15
+ /** @var \Payment_Gateway_Plugin the plugin instance **/
16
+ protected $plugin;
17
+
18
+ /** @var array the token editor for each gateway **/
19
+ protected $token_editors = array();
20
+
21
+ /**
22
+ * Construct the user handler.
23
+ *
24
+ * @since 3.0.0
25
+ * @param \Payment_Gateway_Plugin The plugin instance
26
+ */
27
+ public function __construct( Payment_Gateway_Plugin $plugin ) {
28
+
29
+ $this->plugin = $plugin;
30
+
31
+ // Set up a token editor for each gateway
32
+ add_action( 'admin_init', array( $this, 'init_token_editors' ) );
33
+
34
+ // Add the settings section
35
+ add_action( 'show_user_profile', array( $this, 'add_profile_section' ) );
36
+ add_action( 'edit_user_profile', array( $this, 'add_profile_section' ) );
37
+
38
+ // Save the settings
39
+ add_action( 'personal_options_update', array( $this, 'save_profile_fields' ) );
40
+ add_action( 'edit_user_profile_update', array( $this, 'save_profile_fields' ) );
41
+
42
+ // Display the token editor markup inside the profile section
43
+ add_action( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_user_profile', array( $this, 'display_token_editors' ) );
44
+
45
+ // Display the customer ID field markup inside the profile section
46
+ add_action( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_user_profile', array( $this, 'display_customer_id_fields' ) );
47
+ }
48
+
49
+
50
+ /**
51
+ * Set up a token editor for each gateway.
52
+ *
53
+ * @since 3.0.0
54
+ */
55
+ public function init_token_editors() {
56
+
57
+ foreach ( $this->get_tokenized_gateways() as $gateway ) {
58
+
59
+ if ( ! $gateway->supports_token_editor() ) {
60
+ continue;
61
+ }
62
+
63
+ $this->token_editors[ $gateway->get_id() ] = $gateway->get_payment_tokens_handler()->get_token_editor();
64
+ }
65
+ }
66
+
67
+
68
+ /**
69
+ * Display the customer profile settings markup.
70
+ *
71
+ * @since 3.0.0
72
+ * @param \WP_User $user The user object
73
+ */
74
+ public function add_profile_section( $user ) {
75
+
76
+ if ( ! $this->is_supported() || ! current_user_can( 'manage_woocommerce' ) ) {
77
+ return;
78
+ }
79
+
80
+ $user_id = $user->ID;
81
+ $plugin_id = $this->get_plugin()->get_id();
82
+ $section_title = $this->get_title();
83
+ $section_description = $this->get_description();
84
+
85
+ include( $this->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-user-profile-section.php' );
86
+ }
87
+
88
+
89
+ /**
90
+ * Display the token editor markup.
91
+ *
92
+ * @since 3.0.0
93
+ * @param \WP_User $user The user object
94
+ */
95
+ public function display_token_editors( $user ) {
96
+
97
+ foreach ( $this->get_token_editors() as $gateway_id => $editor ) {
98
+
99
+ $gateway = $this->get_plugin()->get_gateway( $gateway_id );
100
+
101
+ // if the gateway supports a customer ID but none is saved, don't display the token tables
102
+ if ( $gateway && $gateway->supports_customer_id() && ! $gateway->get_customer_id( $user->ID, array( 'autocreate' => false ) ) ) {
103
+ continue;
104
+ }
105
+
106
+ $editor->display( $user->ID );
107
+ }
108
+ }
109
+
110
+
111
+ /**
112
+ * Display the customer ID field(s).
113
+ *
114
+ * @since 3.0.0
115
+ * @param \WP_User $user the user object
116
+ */
117
+ public function display_customer_id_fields( $user ) {
118
+
119
+ foreach( $this->get_customer_id_fields( $user->ID ) as $field ) {
120
+
121
+ $label = $field['label'];
122
+ $name = $field['name'];
123
+ $value = $field['value'];
124
+
125
+ include( $this->get_plugin()->get_payment_gateway_framework_path() . '/admin/views/html-user-profile-field-customer-id.php' );
126
+ }
127
+ }
128
+
129
+
130
+ /**
131
+ * Save the user profile section fields.
132
+ *
133
+ * @since 3.0.0
134
+ * @param int $user_id the user ID
135
+ */
136
+ public function save_profile_fields( $user_id ) {
137
+
138
+ if ( ! $this->is_supported() || ! current_user_can( 'manage_woocommerce' ) ) {
139
+ return;
140
+ }
141
+
142
+ // Save the token data from each token editor
143
+ $this->save_tokens( $user_id );
144
+
145
+ // Save the customer IDs
146
+ $this->save_customer_ids( $user_id );
147
+ }
148
+
149
+
150
+ /**
151
+ * Save the token data from each token editor.
152
+ *
153
+ * @since 3.0.0
154
+ * @param int $user_id the user ID
155
+ */
156
+ protected function save_tokens( $user_id ) {
157
+
158
+ foreach ( $this->get_token_editors() as $gateway_id => $editor ) {
159
+ $editor->save( $user_id );
160
+ }
161
+ }
162
+
163
+
164
+ /**
165
+ * Save the customer IDs.
166
+ *
167
+ * @since 3.0.0
168
+ * @param int $user_id the user ID
169
+ */
170
+ protected function save_customer_ids( $user_id ) {
171
+
172
+ foreach ( $this->get_tokenized_gateways() as $gateway ) {
173
+
174
+ if ( ! $gateway->supports_customer_id() ) {
175
+ continue;
176
+ }
177
+
178
+ if ( isset( $_POST[ $gateway->get_customer_id_user_meta_name() ] ) ) {
179
+ $gateway->update_customer_id( $user_id, trim( $_POST[ $gateway->get_customer_id_user_meta_name() ] ) );
180
+ }
181
+ }
182
+ }
183
+
184
+
185
+ /** Getter methods ******************************************************/
186
+
187
+
188
+ /**
189
+ * Get the token editor section title.
190
+ *
191
+ * @since 3.0.0
192
+ * @return string
193
+ */
194
+ protected function get_title() {
195
+
196
+ $plugin_title = trim( str_replace( 'WooCommerce', '', $this->get_plugin()->get_plugin_name() ) );
197
+
198
+ $title = sprintf( esc_html__( '%s Payment Tokens', 'woocommerce-square' ), $plugin_title );
199
+
200
+ /**
201
+ * Filter the admin token editor title.
202
+ *
203
+ * @since 3.0.0
204
+ * @param string $title The section title
205
+ * @param \Payment_Gateway_Plugin $plugin The gateway plugin instance
206
+ */
207
+ return apply_filters( 'wc_payment_gateway_admin_user_profile_title', $title, $this->get_plugin() );
208
+ }
209
+
210
+
211
+ /**
212
+ * Get the token editor section description.
213
+ *
214
+ * @since 3.0.0
215
+ * @return string
216
+ */
217
+ protected function get_description() {
218
+
219
+ /**
220
+ * Filter the admin token editor description.
221
+ *
222
+ * @since 3.0.0
223
+ * @param string $description The section description
224
+ * @param \Payment_Gateway_Plugin $plugin The gateway plugin instance
225
+ */
226
+ return apply_filters( 'wc_payment_gateway_admin_user_profile_description', '', $this->get_plugin() );
227
+ }
228
+
229
+
230
+ /**
231
+ * Get the token editor objects.
232
+ *
233
+ * @since 3.0.0
234
+ * @return array
235
+ */
236
+ protected function get_token_editors() {
237
+ return $this->token_editors;
238
+ }
239
+
240
+
241
+ /**
242
+ * Get the customer ID fields for the plugin's gateways.
243
+ *
244
+ * In most cases, this will be a single field unless the plugin has multiple gateways and they
245
+ * are set to different environments.
246
+ *
247
+ * @since 3.0.0
248
+ * @param int $user_id the user ID
249
+ * @return array {
250
+ * The fields data
251
+ *
252
+ * @type string $label the field label
253
+ * @type string $name the input name
254
+ * @type string $value the input value
255
+ * }
256
+ */
257
+ protected function get_customer_id_fields( $user_id ) {
258
+
259
+ $unique_meta_key = '';
260
+
261
+ $fields = array();
262
+
263
+ foreach ( $this->get_tokenized_gateways() as $gateway ) {
264
+
265
+ if ( ! $gateway->supports_customer_id() ) {
266
+ continue;
267
+ }
268
+
269
+ $meta_key = $gateway->get_customer_id_user_meta_name();
270
+
271
+ // If a field with this meta key has already been set, skip this gateway
272
+ if ( $meta_key === $unique_meta_key ) {
273
+ continue;
274
+ }
275
+
276
+ $label = esc_html__( 'Customer ID', 'woocommerce-square' );
277
+
278
+ // If the plugin has multiple gateways configured for multiple environments, append the environment name to keep things straight
279
+ $label .= ( $this->has_multiple_environments() ) ? ' ' . sprintf( esc_html__( '(%s)', 'woocommerce-square' ), $gateway->get_environment_name() ) : '';
280
+
281
+ $fields[] = array(
282
+ 'label' => $label,
283
+ 'name' => $meta_key,
284
+ 'value' => $gateway->get_customer_id( $user_id, array(
285
+ 'autocreate' => false,
286
+ ) ),
287
+ );
288
+
289
+ $unique_meta_key = $meta_key;
290
+ }
291
+
292
+ return $fields;
293
+ }
294
+
295
+
296
+ /**
297
+ * Get the unique environments between the plugin's gateways.
298
+ *
299
+ * @since 3.0.0
300
+ * @return array the environments in the format `$environment_id => $environment_name`
301
+ */
302
+ protected function get_unique_environments() {
303
+
304
+ $environments = array();
305
+
306
+ foreach ( $this->get_tokenized_gateways() as $gateway ) {
307
+ $environments[ $gateway->get_environment() ] = $gateway->get_environment_name();
308
+ }
309
+
310
+ $environments = array_unique( $environments );
311
+
312
+ return $environments;
313
+ }
314
+
315
+
316
+ /**
317
+ * Get the gateways that support tokenization and are enabled.
318
+ *
319
+ * @since 3.0.0
320
+ * @return array
321
+ */
322
+ protected function get_tokenized_gateways() {
323
+
324
+ $gateways = array();
325
+
326
+ foreach ( $this->get_plugin()->get_gateways() as $gateway ) {
327
+
328
+ if ( $gateway->is_enabled() && $gateway->supports_tokenization() && ( $gateway->supports_token_editor() || $gateway->supports_customer_id() ) ) {
329
+ $gateways[] = $gateway;
330
+ }
331
+ }
332
+
333
+ return $gateways;
334
+ }
335
+
336
+
337
+ /** Conditional methods ******************************************************/
338
+
339
+
340
+ /**
341
+ * Determine if the user profile section is supported by at least one gateway.
342
+ *
343
+ * @since 3.0.0
344
+ * @return bool
345
+ */
346
+ protected function is_supported() {
347
+
348
+ $gateways = $this->get_tokenized_gateways();
349
+
350
+ /**
351
+ * Filter whether the user profile section should be displayed for this gateway plugin.
352
+ *
353
+ * @since 3.0.0
354
+ * @param bool $display
355
+ * @param \Payment_Gateway_Plugin $plugin the gateway plugin instance
356
+ */
357
+ return apply_filters( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_display_user_profile', ! empty( $gateways ), $this->get_plugin() );
358
+ }
359
+
360
+
361
+ /**
362
+ * Determine if the plugin has varying environments between its gateways.
363
+ *
364
+ * @since 3.0.0
365
+ * @return bool
366
+ */
367
+ public function has_multiple_environments() {
368
+ return 1 < count( $this->get_unique_environments() );
369
+ }
370
+
371
+
372
+ /**
373
+ * Get the plugin instance.
374
+ *
375
+ * @since 3.0.0
376
+ * @return \Payment_Gateway_Plugin the plugin instance
377
+ */
378
+ protected function get_plugin() {
379
+ return $this->plugin;
380
+ }
381
+ }
includes/Framework/PaymentGateway/Admin/views/html-admin-gateway-status.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <table class="wc_status_table widefat" cellspacing="0">
2
+
3
+ <thead>
4
+ <tr>
5
+ <th colspan="3" data-export-label="">
6
+ <?php echo esc_html( $gateway->get_method_title() ); ?>
7
+ <?php echo wc_help_tip( __( 'This section contains configuration settings for this gateway.', 'woocommerce-square' ) ); ?>
8
+ </th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <tbody>
13
+
14
+ <?php
15
+ /**
16
+ * Payment Gateway System Status Start Action.
17
+ *
18
+ * Allow actors to add info the start of the gateway system status section.
19
+ *
20
+ * @since 4.3.0
21
+ *
22
+ * @param Payment_Gateway $gateway
23
+ */
24
+ do_action( 'wc_payment_gateway_' . $gateway->get_id() . '_system_status_start', $gateway );
25
+ ?>
26
+
27
+ <tr>
28
+ <td data-export-label="Environment"><?php esc_html_e( 'Environment', 'woocommerce-square' ); ?>:</td>
29
+ <td class="help"><?php echo wc_help_tip( __( 'The transaction environment for this gateway.', 'woocommerce-square' ) ); ?></td>
30
+ <td><?php echo esc_html( $environment ); ?></td>
31
+ </tr>
32
+
33
+ <?php if ( $gateway->supports_tokenization() ) : ?>
34
+
35
+ <tr>
36
+ <td data-export-label="Tokenization Enabled"><?php esc_html_e( 'Tokenization Enabled', 'woocommerce-square' ); ?>:</td>
37
+ <td class="help"><?php echo wc_help_tip( __( 'Displays whether or not tokenization is enabled for this gateway.', 'woocommerce-square' ) ); ?></td>
38
+ <td>
39
+ <?php if ( $gateway->tokenization_enabled() ) : ?>
40
+ <mark class="yes">&#10004;</mark>
41
+ <?php else : ?>
42
+ <mark class="no">&ndash;</mark>
43
+ <?php endif; ?>
44
+ </td>
45
+ </tr>
46
+
47
+ <?php endif; ?>
48
+
49
+ <tr>
50
+ <td data-export-label="Debug Mode"><?php esc_html_e( 'Debug Mode', 'woocommerce-square' ); ?>:</td>
51
+ <td class="help"><?php echo wc_help_tip( __( 'Displays whether or not debug logging is enabled for this gateway.', 'woocommerce-square' ) ); ?></td>
52
+ <td>
53
+ <?php if ( $gateway->debug_log() && $gateway->debug_checkout() ) : ?>
54
+ <?php echo esc_html__( 'Display at Checkout & Log', 'woocommerce-square' ); ?>
55
+ <?php elseif ( $gateway->debug_checkout() ) : ?>
56
+ <?php echo esc_html__( 'Display at Checkout', 'woocommerce-square' ); ?>
57
+ <?php elseif ( $gateway->debug_log() ) : ?>
58
+ <?php echo esc_html__( 'Save to Log', 'woocommerce-square' ); ?>
59
+ <?php else : ?>
60
+ <?php echo esc_html__( 'Off', 'woocommerce-square' ); ?>
61
+ <?php endif; ?>
62
+ </td>
63
+ </tr>
64
+
65
+ <?php
66
+ /**
67
+ * Payment Gateway System Status End Action.
68
+ *
69
+ * Allow actors to add info the end of the gateway system status section.
70
+ *
71
+ * @since 4.3.0
72
+ * @param \Payment_Gateway $gateway
73
+ */
74
+ do_action( 'wc_payment_gateway_' . $gateway->get_id() . '_system_status_end', $gateway );
75
+ ?>
76
+
77
+ </tbody>
78
+
79
+ </table>
includes/Framework/PaymentGateway/Admin/views/html-order-partial-capture.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wc-order-data-row wc-order-data-row-toggle sv-wc-payment-gateway-partial-capture wc-<?php echo esc_attr( $gateway->get_id_dasherized() ); ?>-partial-capture" style="display:none;">
2
+ <table class="wc-order-totals">
3
+
4
+ <tr>
5
+ <td class="label"><?php esc_html_e( 'Authorization total', 'woocommerce-square' ); ?>:</td>
6
+ <td class="total"><?php echo wc_price( $authorization_total, array( 'currency' => $order->get_currency() ) ); ?></td>
7
+ </tr>
8
+ <tr>
9
+ <td class="label"><?php esc_html_e( 'Amount already captured', 'woocommerce-square' ); ?>:</td>
10
+ <td class="total"><?php echo wc_price( $total_captured, array( 'currency' => $order->get_currency() ) ); ?></td>
11
+ </tr>
12
+
13
+ <?php if ( $remaining_total > 0 ) : ?>
14
+ <tr>
15
+ <td class="label"><?php esc_html_e( 'Remaining order total', 'woocommerce-square' ); ?>:</td>
16
+ <td class="total"><?php echo wc_price( $remaining_total, array( 'currency' => $order->get_currency() ) ); ?></td>
17
+ </tr>
18
+ <?php endif; ?>
19
+
20
+ <tr>
21
+ <td class="label"><label for="capture_amount"><?php esc_html_e( 'Capture amount', 'woocommerce-square' ); ?>:</label></td>
22
+ <td class="total">
23
+ <input type="text" class="text" id="capture_amount" name="capture_amount" class="wc_input_price" />
24
+ <div class="clear"></div>
25
+ </td>
26
+ </tr>
27
+ <tr>
28
+ <td class="label"><label for="capture_comment"><?php esc_html_e( 'Comment (optional):', 'woocommerce-square' ); ?></label></td>
29
+ <td class="total">
30
+ <input type="text" class="text" id="capture_comment" name="capture_comment" />
31
+ <div class="clear"></div>
32
+ </td>
33
+ </tr>
34
+ </table>
35
+ <div class="clear"></div>
36
+ <div class="capture-actions">
37
+
38
+ <?php $amount = '<span class="capture-amount">' . wc_price( 0, array( 'currency' => $order->get_currency() ) ) . '</span>'; ?>
39
+
40
+ <button type="button" class="button button-primary capture-action" disabled="disabled"><?php printf( esc_html__( 'Capture %s', 'woocommerce-square' ), $amount ); ?></button>
41
+ <button type="button" class="button cancel-action"><?php _e( 'Cancel', 'woocommerce-square' ); ?></button>
42
+
43
+ <div class="clear"></div>
44
+ </div>
45
+ </div>
includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor-token.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $token_input_name = $input_name . '[' . $index . ']'; ?>
2
+
3
+ <tr class="token <?php echo ! $token['id'] ? 'new-token' : ''; ?>">
4
+
5
+ <?php foreach ( $fields as $field_id => $field ) : ?>
6
+
7
+ <?php $is_select = 'select' === $field['type'] && isset( $field['options'] ) && ! empty( $field['options'] ); ?>
8
+
9
+ <td class="token-<?php echo esc_attr( $field_id ); ?>">
10
+
11
+ <?php if ( ! $field['editable'] ) : ?>
12
+
13
+ <?php $display_value = $is_select && ! empty( $field['options'][ $token[ $field_id ] ] ) ? $field['options'][ $token[ $field_id ] ] : $token[ $field_id ]; ?>
14
+
15
+ <span class="token-<?php echo esc_attr( $field_id ); ?> token-attribute"><?php echo esc_attr( $display_value ); ?></span>
16
+
17
+ <input name="<?php echo esc_attr( $token_input_name ); ?>[<?php echo esc_attr( $field_id ); ?>]" value="<?php echo esc_attr( $token[ $field_id ] ); ?>" type="hidden" />
18
+
19
+ <?php elseif ( $is_select ) : ?>
20
+
21
+ <select name="<?php echo esc_attr( $token_input_name ); ?>[<?php echo esc_attr( $field_id ); ?>]">
22
+
23
+ <option value=""><?php esc_html_e( '-- Select an option --', 'woocommerce-square' ); ?></option>
24
+
25
+ <?php foreach ( $field['options'] as $value => $label ) : ?>
26
+ <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $token[ $field_id ] ); ?>><?php echo esc_html( $label ); ?></option>
27
+ <?php endforeach; ?>
28
+
29
+ </select>
30
+
31
+ <?php else : ?>
32
+
33
+ <?php // Build the input attributes
34
+ $attributes = array();
35
+
36
+ foreach ( $field['attributes'] as $name => $value ) {
37
+ $attributes[] = esc_attr( $name ) . '="' . esc_attr( $value ) . '"';
38
+ } ?>
39
+
40
+ <input
41
+ name="<?php echo esc_attr( $token_input_name ); ?>[<?php echo esc_attr( $field_id ); ?>]"
42
+ value="<?php echo esc_attr( $token[ $field_id ] ); ?>"
43
+ type="text"
44
+ <?php echo implode( ' ', $attributes ); ?>
45
+ <?php echo $field['required'] ? 'required' : ''; ?>
46
+ />
47
+
48
+ <?php endif; ?>
49
+
50
+ </td>
51
+
52
+ <?php endforeach; ?>
53
+
54
+ <input name="<?php echo esc_attr( $token_input_name ); ?>[type]" value="<?php echo esc_attr( $type ); ?>" type="hidden" />
55
+
56
+ <td class="token-default token-attribute">
57
+ <input name="<?php echo esc_attr( $input_name ); ?>_default" value="<?php echo esc_attr( $token['id'] ); ?>" type="radio" <?php checked( true, $token['default'] ); ?>/>
58
+ </td>
59
+
60
+ <?php // Token actions ?>
61
+ <td class="token-actions">
62
+
63
+ <?php foreach ( $actions as $action => $label ) : ?>
64
+ <button class="sv-wc-payment-gateway-token-action-button button" data-action="<?php echo esc_attr( $action ); ?>" data-token-id="<?php echo esc_attr( $token['id'] ); ?>" data-user-id="<?php echo esc_attr( $user_id ); ?>">
65
+ <?php echo esc_attr( $label ); ?>
66
+ </button>
67
+ <?php endforeach; ?>
68
+
69
+ </td>
70
+
71
+ </tr>
includes/Framework/PaymentGateway/Admin/views/html-user-payment-token-editor.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+
3
+ <th><?php echo esc_html( $title ); ?></th>
4
+
5
+ <td class="forminp">
6
+
7
+ <table class="sv_wc_payment_gateway_token_editor widefat" data-gateway-id="<?php echo esc_attr( $id ); ?>">
8
+
9
+ <thead>
10
+ <tr>
11
+
12
+ <?php // Display a column for each token field
13
+ foreach ( $columns as $column_id => $column_title ) : ?>
14
+ <th class="token-<?php echo esc_attr( $column_id ); ?>"><?php echo esc_html( $column_title ); ?></th>
15
+ <?php endforeach; ?>
16
+
17
+ </tr>
18
+ </thead>
19
+
20
+ <tbody class="tokens">
21
+
22
+ <?php
23
+ /** Fire inside the payment gateway token editor.
24
+ *
25
+ * @since 4.3.0
26
+ * @param int $user_id the current user ID
27
+ */
28
+ do_action( 'wc_payment_gateway_' . $id . '_token_editor_tokens', $user_id ); ?>
29
+
30
+ </tbody>
31
+
32
+ <tbody class="meta">
33
+ <tr class="no-tokens">
34
+ <td colspan="<?php echo count( $columns ); ?>"><?php esc_html_e( 'No saved payment tokens', 'woocommerce-square' ); ?></td>
35
+ </tr>
36
+ </tbody>
37
+
38
+ <?php // Editor actions
39
+ if ( ! empty( $actions ) ) : ?>
40
+
41
+ <tfoot>
42
+ <tr>
43
+ <th class="actions" colspan="<?php echo count( $columns ); ?>">
44
+
45
+ <?php foreach ( $actions as $action => $label ) : ?>
46
+
47
+ <?php $button_class = 'save' === $action ? 'button-primary' : 'button'; ?>
48
+
49
+ <button class="sv-wc-payment-gateway-token-editor-action-button <?php echo sanitize_html_class( $button_class ); ?>" data-action="<?php echo esc_attr( $action ); ?>" data-user-id="<?php echo esc_attr( $user_id ); ?>">
50
+ <?php echo esc_attr( $label ); ?>
51
+ </button>
52
+
53
+ <?php endforeach; ?>
54
+
55
+ </th>
56
+ </tr>
57
+ </tfoot>
58
+
59
+ <?php endif; ?>
60
+
61
+ </table>
62
+
63
+ </td>
64
+
65
+ </tr>
includes/Framework/PaymentGateway/Admin/views/html-user-profile-field-customer-id.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th><label for="<?php echo esc_attr( $name ); ?>"><?php echo esc_html( $label ); ?></label></th>
3
+ <td>
4
+ <input class="regular-text" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" type="text" /><br/>
5
+ <span class="description"><?php esc_html_e( 'The gateway customer ID for the user. Only edit this if necessary.', 'woocommerce-square' ); ?></span>
6
+ </td>
7
+ </tr>
includes/Framework/PaymentGateway/Admin/views/html-user-profile-section.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="wc_payment_gateway_<?php echo esc_attr( $plugin_id ); ?>_user_settings" class="sv_wc_payment_gateway_user_settings woocommerce">
2
+
3
+ <h3><?php echo esc_html( $section_title ); ?></h3>
4
+
5
+ <?php if ( ! empty( $section_description ) ) : ?>
6
+ <p><?php echo wp_kses_post( $section_description ); ?></p>
7
+ <?php endif; ?>
8
+
9
+ <table class="form-table">
10
+
11
+ <tbody>
12
+
13
+ <?php
14
+ /** Fire inside the payment gateway user settings section.
15
+ *
16
+ * @since 4.3.0
17
+ * @param \WP_User $user the current user object
18
+ */
19
+ do_action( 'wc_payment_gateway_' . $plugin_id . '_user_profile', $user ); ?>
20
+
21
+ </tbody>
22
+
23
+ </table>
24
+
25
+ </div>
includes/Framework/PaymentGateway/Api/Payment_Gateway_API_Response.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+ use WooCommerce\Square\Framework\Api\API_Response;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * WooCommerce Direct Payment Gateway API Response
10
+ */
11
+ interface Payment_Gateway_API_Response extends API_Response {
12
+
13
+ /**
14
+ * Checks if the transaction was successful.
15
+ *
16
+ * @since 3.0.0
17
+ *
18
+ * @return bool true if approved, false otherwise
19
+ */
20
+ public function transaction_approved();
21
+
22
+
23
+ /**
24
+ * Returns true if the transaction was held, for instance due to AVS/CSC
25
+ * Fraud Settings. This indicates that the transaction was successful, but
26
+ * did not pass a fraud check and should be reviewed.
27
+ *
28
+ * @since 3.0.0
29
+ *
30
+ * @return bool true if the transaction was held, false otherwise
31
+ */
32
+ public function transaction_held();
33
+
34
+
35
+ /**
36
+ * Gets the response status message, or null if there is no status message
37
+ * associated with this transaction.
38
+ *
39
+ * @since 3.0.0
40
+ *
41
+ * @return string status message
42
+ */
43
+ public function get_status_message();
44
+
45
+
46
+ /**
47
+ * Gets the response status code, or null if there is no status code
48
+ * associated with this transaction.
49
+ *
50
+ * @since 3.0.0
51
+ *
52
+ * @return string status code
53
+ */
54
+ public function get_status_code();
55
+
56
+
57
+ /**
58
+ * Gets the response transaction id, or null if there is no transaction id
59
+ * associated with this transaction.
60
+ *
61
+ * @since 3.0.0
62
+ *
63
+ * @return string transaction id
64
+ */
65
+ public function get_transaction_id();
66
+
67
+
68
+ /**
69
+ * Gets the payment type: 'credit-card', 'echeck', etc...
70
+ *
71
+ * @since 3.0.0
72
+ *
73
+ * @return string
74
+ */
75
+ public function get_payment_type();
76
+
77
+
78
+ /**
79
+ * Returns a message appropriate for a frontend user. This should be used
80
+ * to provide enough information to a user to allow them to resolve an
81
+ * issue on their own, but not enough to help nefarious folks fishing for
82
+ * info.
83
+ *
84
+ * @see Payment_Gateway_API_Response_Message_Helper
85
+ *
86
+ * @since 3.0.0
87
+ *
88
+ * @return string user message, if there is one
89
+ */
90
+ public function get_user_message();
91
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * WooCommerce Direct Payment Gateway API
9
+ */
10
+ interface Payment_Gateway_API {
11
+
12
+
13
+ /**
14
+ * Perform a credit card authorization for the given order
15
+ *
16
+ * If the gateway does not support credit card authorizations, this method can be a no-op.
17
+ *
18
+ * @since 3.0.0
19
+ *
20
+ * @param \WC_Order $order the order
21
+ * @return Payment_Gateway_API_Response credit card charge response
22
+ * @throws \Exception network timeouts, etc
23
+ */
24
+ public function credit_card_authorization( \WC_Order $order );
25
+
26
+
27
+ /**
28
+ * Perform a credit card charge for the given order
29
+ *
30
+ * If the gateway does not support credit card charges, this method can be a no-op.
31
+ *
32
+ * @since 3.0.0
33
+ *
34
+ * @param \WC_Order $order the order
35
+ * @return Payment_Gateway_API_Response credit card charge response
36
+ * @throws \Exception network timeouts, etc
37
+ */
38
+ public function credit_card_charge( \WC_Order $order );
39
+
40
+
41
+ /**
42
+ * Perform a credit card capture for a given authorized order
43
+ *
44
+ * If the gateway does not support credit card capture, this method can be a no-op.
45
+ *
46
+ * @since 3.0.0
47
+ *
48
+ * @param \WC_Order $order the order
49
+ * @return Payment_Gateway_API_Response credit card capture response
50
+ * @throws \Exception network timeouts, etc
51
+ */
52
+ public function credit_card_capture( \WC_Order $order );
53
+
54
+
55
+ /**
56
+ * Perform an eCheck debit (ACH transaction) for the given order
57
+ *
58
+ * If the gateway does not support check debits, this method can be a no-op.
59
+ *
60
+ * @since 3.0.0
61
+ *
62
+ * @param \WC_Order $order the order
63
+ * @return Payment_Gateway_API_Response check debit response
64
+ * @throws \Exception network timeouts, etc
65
+ */
66
+ public function check_debit( \WC_Order $order );
67
+
68
+
69
+ /**
70
+ * Perform a refund for the given order
71
+ *
72
+ * If the gateway does not support refunds, this method can be a no-op.
73
+ *
74
+ * @since 3.0.0
75
+ *
76
+ * @param \WC_Order $order order object
77
+ * @return Payment_Gateway_API_Response refund response
78
+ * @throws \Exception network timeouts, etc
79
+ */
80
+ public function refund( \WC_Order $order );
81
+
82
+
83
+ /**
84
+ * Perform a void for the given order
85
+ *
86
+ * If the gateway does not support voids, this method can be a no-op.
87
+ *
88
+ * @since 3.0.0
89
+ *
90
+ * @param \WC_Order $order order object
91
+ * @return Payment_Gateway_API_Response void response
92
+ * @throws \Exception network timeouts, etc
93
+ */
94
+ public function void( \WC_Order $order );
95
+
96
+
97
+ /**
98
+ * Creates a payment token for the given order
99
+ *
100
+ * If the gateway does not support tokenization, this method can be a no-op.
101
+ *
102
+ * @since 3.0.0
103
+ *
104
+ * @param \WC_Order $order the order
105
+ * @return Payment_Gateway_API_Create_Payment_Token_Response payment method tokenization response
106
+ * @throws \Exception network timeouts, etc
107
+ */
108
+ public function tokenize_payment_method( \WC_Order $order );
109
+
110
+
111
+ /**
112
+ * Updates a tokenized payment method.
113
+ *
114
+ * @since 3.0.0
115
+ *
116
+ * @param \WC_Order $order order object
117
+ * @return Payment_Gateway_API_Response
118
+ * @throws \Exception
119
+ */
120
+ public function update_tokenized_payment_method( \WC_Order $order );
121
+
122
+
123
+ /**
124
+ * Determines if this API supports updating tokenized payment methods.
125
+ *
126
+ * @see Payment_Gateway_API::update_tokenized_payment_method()
127
+ *
128
+ * @since 3.0.0
129
+ *
130
+ * @return bool
131
+ */
132
+ public function supports_update_tokenized_payment_method();
133
+
134
+
135
+ /**
136
+ * Removes the tokenized payment method. This method should not be invoked
137
+ * unless supports_remove_tokenized_payment_method() returns true, otherwise
138
+ * the results are undefined.
139
+ *
140
+ * @since 3.0.0
141
+ * @see Payment_Gateway_API::supports_remove_tokenized_payment_method()
142
+ *
143
+ * @param string $token the payment method token
144
+ * @param string $customer_id unique customer id for gateways that support it
145
+ * @return Payment_Gateway_API_Response remove tokenized payment method response
146
+ * @throws \Exception network timeouts, etc
147
+ */
148
+ public function remove_tokenized_payment_method( $token, $customer_id );
149
+
150
+
151
+ /**
152
+ * Returns true if this API supports a "remove tokenized payment method"
153
+ * request. If this method returns true, then remove_tokenized_payment_method()
154
+ * is considered safe to call.
155
+ *
156
+ * @since 3.0.0
157
+ * @see Payment_Gateway_API::remove_tokenized_payment_method()
158
+ *
159
+ * @return boolean true if this API supports a "remove tokenized payment method" request, false otherwise
160
+ */
161
+ public function supports_remove_tokenized_payment_method();
162
+
163
+
164
+ /**
165
+ * Returns all tokenized payment methods for the customer. This method
166
+ * should not be invoked unless supports_get_tokenized_payment_methods()
167
+ * return true, otherwise the results are undefined
168
+ *
169
+ * @since 3.0.0
170
+ * @see Payment_Gateway_API::supports_get_tokenized_payment_methods()
171
+ *
172
+ * @param string $customer_id unique customer id
173
+ * @return Payment_Gateway_API_Get_Tokenized_Payment_Methods_Response response containing any payment tokens for the customer
174
+ * @throws \Exception network timeouts, etc
175
+ */
176
+ public function get_tokenized_payment_methods( $customer_id );
177
+
178
+
179
+ /**
180
+ * Returns true if this API supports a "get tokenized payment methods"
181
+ * request. If this method returns true, then get_tokenized_payment_methods()
182
+ * is considered safe to call.
183
+ *
184
+ * @since 3.0.0
185
+ * @see Payment_Gateway_API::get_tokenized_payment_methods()
186
+ *
187
+ * @return boolean true if this API supports a "get tokenized payment methods" request, false otherwise
188
+ */
189
+ public function supports_get_tokenized_payment_methods();
190
+
191
+
192
+ /**
193
+ * Returns the most recent request object
194
+ *
195
+ * @since 3.0.0
196
+ *
197
+ * @return \WooCommerce\Square\Framework\Api\API_Request the most recent request object
198
+ */
199
+ public function get_request();
200
+
201
+
202
+ /**
203
+ * Returns the most recent response object
204
+ *
205
+ * @since 3.0.0
206
+ *
207
+ * @return Payment_Gateway_API_Response the most recent response object
208
+ */
209
+ public function get_response();
210
+
211
+
212
+ /**
213
+ * Returns the WC_Order object associated with the request, if any
214
+ *
215
+ * @since 3.0.0
216
+ *
217
+ * @return \WC_Order
218
+ */
219
+ public function get_order();
220
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Authorization_Response.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * WooCommerce Direct Payment Gateway API Authorization Response
9
+ *
10
+ * Represents a Payment Gateway Credit Card Authorization response. This should
11
+ * also be used as the parent class for credit card charge (authorization +
12
+ * capture) responses.
13
+ */
14
+ interface Payment_Gateway_API_Authorization_Response extends Payment_Gateway_API_Response {
15
+
16
+ /**
17
+ * The authorization code is returned from the credit card processor to
18
+ * indicate that the charge will be paid by the card issuer.
19
+ *
20
+ * @since 3.0.0
21
+ *
22
+ * @return string credit card authorization code
23
+ */
24
+ public function get_authorization_code();
25
+
26
+
27
+ /**
28
+ * Returns the result of the AVS check.
29
+ *
30
+ * @since 3.0.0
31
+ *
32
+ * @return string result of the AVS check, if any
33
+ */
34
+ public function get_avs_result();
35
+
36
+
37
+ /**
38
+ * Returns the result of the CSC check.
39
+ *
40
+ * @since 3.0.0
41
+ *
42
+ * @return string result of CSC check
43
+ */
44
+ public function get_csc_result();
45
+
46
+
47
+ /**
48
+ * Returns true if the CSC check was successful.
49
+ *
50
+ * @since 3.0.0
51
+ *
52
+ * @return boolean true if the CSC check was successful
53
+ */
54
+ public function csc_match();
55
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Create_Payment_Token_Response.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Response;
5
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Token;
6
+
7
+ defined( 'ABSPATH' ) or exit;
8
+
9
+ /**
10
+ * WooCommerce Direct Payment Gateway API Create Payment Token Response
11
+ */
12
+ interface Payment_Gateway_API_Create_Payment_Token_Response extends Payment_Gateway_API_Response {
13
+
14
+ /**
15
+ * Returns the payment token.
16
+ *
17
+ * @since 3.0.0
18
+ *
19
+ * @return Payment_Gateway_Payment_Token payment token
20
+ */
21
+ public function get_payment_token();
22
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Customer_Response.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * WooCommerce Direct Payment Gateway API Customer Response
9
+ */
10
+ interface Payment_Gateway_API_Customer_Response extends Payment_Gateway_API_Response {
11
+ /**
12
+ * Returns the customer ID.
13
+ *
14
+ * @since 3.0.0
15
+ *
16
+ * @return string customer ID returned by the gateway
17
+ */
18
+ public function get_customer_id();
19
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Get_Tokenized_Payment_Methods_Response.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
4
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Token;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * WooCommerce Direct Payment Gateway API Create Payment Token Response
10
+ */
11
+ interface Payment_Gateway_API_Get_Tokenized_Payment_Methods_Response extends Payment_Gateway_API_Response {
12
+
13
+ /**
14
+ * Returns any payment tokens.
15
+ *
16
+ * @since 3.0.0
17
+ *
18
+ * @return Payment_Gateway_Payment_Token[] array of Payment_Gateway_Payment_Token payment tokens, keyed by the token ID
19
+ */
20
+ public function get_payment_tokens();
21
+ }
includes/Framework/PaymentGateway/Api/Payment_Gateway_Api_Response_Message_Helper.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WooCommerce\Square\Framework\PaymentGateway\Api;
3
+
4
+ defined( 'ABSPATH' ) or exit;
5
+
6
+ /**
7
+ * WooCommerce Payment Gateway API Response Message Helper
8
+ *
9
+ * This utility class is meant to provide a standard set of error messages to be
10
+ * displayed to the customer during checkout.
11
+ *
12
+ * @since 3.0.0
13
+ */
14
+ class Payment_Gateway_API_Response_Message_Helper {
15
+
16
+ /**
17
+ * Returns a message appropriate for a frontend user. This should be used
18
+ * to provide enough information to a user to allow them to resolve an
19
+ * issue on their own, but not enough to help nefarious folks fishing for
20
+ * info.
21
+ *
22
+ * @since 3.0.0
23
+ * @param string $message_id identifies the message to return
24
+ * @return string a user message
25
+ */
26
+ public function get_user_message( $message_id ) {
27
+
28
+ $message = null;
29
+
30
+ switch ( $message_id ) {
31
+
32
+ // generic messages
33
+ case 'error': $message = esc_html__( 'An error occurred, please try again or try an alternate form of payment', 'woocommerce-square' ); break;
34
+ case 'decline': $message = esc_html__( 'We cannot process your order with the payment information that you provided. Please use a different payment account or an alternate payment method.', 'woocommerce-square' ); break;
35
+ case 'held_for_review': $message = esc_html__( 'This order is being placed on hold for review. Please contact us to complete the transaction.', 'woocommerce-square' ); break;
36
+
37
+ /* missing/invalid info */
38
+
39
+ // csc
40
+ case 'held_for_incorrect_csc': $message = esc_html__( 'This order is being placed on hold for review due to an incorrect card verification number. You may contact the store to complete the transaction.', 'woocommerce-square' ); break;
41
+ case 'csc_invalid': $message = esc_html__( 'The card verification number is invalid, please try again.', 'woocommerce-square' ); break;
42
+ case 'csc_missing': $message = esc_html__( 'Please enter your card verification number and try again.', 'woocommerce-square' ); break;
43
+
44
+ // card type
45
+ case 'card_type_not_accepted': $message = esc_html__( 'That card type is not accepted, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
46
+ case 'card_type_invalid': $message = esc_html__( 'The card type is invalid or does not correlate with the credit card number. Please try again or use an alternate card or other form of payment.', 'woocommerce-square' ); break;
47
+ case 'card_type_missing': $message = esc_html__( 'Please select the card type and try again.', 'woocommerce-square' ); break;
48
+
49
+ // card number
50
+ case 'card_number_type_invalid': $message = esc_html__( 'The card type is invalid or does not correlate with the credit card number. Please try again or use an alternate card or other form of payment.', 'woocommerce-square' ); break;
51
+ case 'card_number_invalid': $message = esc_html__( 'The card number is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
52
+ case 'card_number_missing': $message = esc_html__( 'Please enter your card number and try again.', 'woocommerce-square' ); break;
53
+
54
+ // card expiry
55
+ case 'card_expiry_invalid': $message = esc_html__( 'The card expiration date is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
56
+ case 'card_expiry_month_invalid': $message = esc_html__( 'The card expiration month is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
57
+ case 'card_expiry_year_invalid': $message = esc_html__( 'The card expiration year is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
58
+ case 'card_expiry_missing': $message = esc_html__( 'Please enter your card expiration date and try again.', 'woocommerce-square' ); break;
59
+
60
+ // bank
61
+ case 'bank_aba_invalid': $message_id = esc_html__( 'The bank routing number is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
62
+ case 'bank_account_number_invalid': $message_id = esc_html__( 'The bank account number is invalid, please re-enter and try again.', 'woocommerce-square' ); break;
63
+
64
+ /* decline reasons */
65
+ case 'card_expired': $message = esc_html__( 'The provided card is expired, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
66
+ case 'card_declined': $message = esc_html__( 'The provided card was declined, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
67
+ case 'insufficient_funds': $message = esc_html__( 'Insufficient funds in account, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
68
+ case 'card_inactive': $message = esc_html__( 'The card is inactivate or not authorized for card-not-present transactions, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
69
+ case 'credit_limit_reached': $message = esc_html__( 'The credit limit for the card has been reached, please use an alternate card or other form of payment.', 'woocommerce-square' ); break;
70
+ case 'csc_mismatch': $message = esc_html__( 'The card verification number does not match. Please re-enter and try again.', 'woocommerce-square' ); break;
71
+ case 'avs_mismatch': $message = esc_html__( 'The provided address does not match the billing address for cardholder. Please verify the address and try again.', 'woocommerce-square' ); break;
72
+ }
73
+
74
+ /**
75
+ * Payment Gateway API Response User Message Filter.
76
+ *
77
+ * Allow actors to modify the error message returned to a user when a transaction
78
+ * has encountered an error and the admin has enabled the "show detailed
79
+ * decline messages" setting
80
+ *
81
+ * @since 3.0.0
82
+ * @param string $message message to show to user
83
+ * @param string $message_id machine code for the message, e.g. card_expired
84
+ * @param Payment_Gateway_API_Response_Message_Helper $this instance
85
+ */
86
+ return apply_filters( 'wc_payment_gateway_transaction_response_user_message', $message, $message_id, $this );
87
+ }
88
+ }
includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Payment Gateway API class
4
+ *
5
+ * This file describes a class that provides an API to communicate
6
+ * with Apply Pay features.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api;
14
+ use WooCommerce\Square\Framework as SquareFramework;
15
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
16
+
17
+ defined( 'ABSPATH' ) or exit;
18
+
19
+ /**
20
+ * Sets up the Apple Pay API.
21
+ *
22
+ * @since 3.0.0
23
+ */
24
+ class Payment_Gateway_Apple_Pay_API extends SquareFramework\Api\Base {
25
+
26
+
27
+ /** @var SquareFramework\PaymentGateway\Payment_Gateway the gateway instance */
28
+ protected $gateway;
29
+
30
+
31
+ /**
32
+ * Constructs the class.
33
+ *
34
+ * @since 3.0.0
35
+ *
36
+ * @param SquareFramework\PaymentGateway\Payment_Gateway the gateway instance
37
+ */
38
+ public function __construct( SquareFramework\PaymentGateway\Payment_Gateway $gateway ) {
39
+
40
+ $this->gateway = $gateway;
41
+
42
+ $this->request_uri = 'https://apple-pay-gateway-cert.apple.com/paymentservices/startSession';
43
+
44
+ $this->set_request_content_type_header( 'application/json' );
45
+ $this->set_request_accept_header( 'application/json' );
46
+ $this->set_response_handler( '\\WooCommerce\\Square\\Framework\\PaymentGateway\\ApplePay\\Api\\Payment_Gateway_Apple_Pay_API_Response' );
47
+ }
48
+
49
+
50
+ /**
51
+ * Validates the Apple Pay merchant.
52
+ *
53
+ * @since 3.0.0
54
+ *
55
+ * @param string $url the validation URL
56
+ * @param string $merchant_id the merchant ID to validate
57
+ * @param string $domain_name the verified domain name
58
+ * @param string $display_name the merchant display name
59
+ * @return Payment_Gateway_Apple_Pay_API_Response the response object
60
+ * @throws \Exception
61
+ */
62
+ public function validate_merchant( $url, $merchant_id, $domain_name, $display_name ) {
63
+
64
+ $this->request_uri = $url;
65
+
66
+ $request = $this->get_new_request();
67
+
68
+ $request->set_merchant_data( $merchant_id, $domain_name, $display_name );
69
+
70
+ return $this->perform_request( $request );
71
+ }
72
+
73
+
74
+ /**
75
+ * Performs the request and return the parsed response.
76
+ *
77
+ * @since 3.0.0
78
+ *
79
+ * @param SquareFramework\Api\API_Request|object
80
+ * @return SquareFramework\Api\API_Response|object
81
+ * @throws \Exception
82
+ */
83
+ protected function perform_request( $request ) {
84
+
85
+ // set PEM file cert for requests
86
+ add_action( 'http_api_curl', array( $this, 'set_cert_file' ) );
87
+
88
+ return parent::perform_request( $request );
89
+ }
90
+
91
+
92
+ /**
93
+ * Sets the PEM file required for authentication.
94
+ *
95
+ * @internal
96
+ *
97
+ * @since 3.0.0
98
+ *
99
+ * @param resource $curl_handle
100
+ */
101
+ public function set_cert_file( $curl_handle ) {
102
+
103
+ if ( ! $curl_handle ) {
104
+ return;
105
+ }
106
+
107
+ curl_setopt( $curl_handle, CURLOPT_SSLCERT, get_option( 'sv_wc_apple_pay_cert_path' ) );
108
+ }
109
+
110
+
111
+ /** Validation methods ****************************************************/
112
+
113
+
114
+ /**
115
+ * Validates the post-parsed response.
116
+ *
117
+ * @since 3.0.0
118
+ *
119
+ * @return bool
120
+ *
121
+ * @throws \Exception
122
+ */
123
+ protected function do_post_parse_response_validation() {
124
+
125
+ $response = $this->get_response();
126
+
127
+ if ( $response->get_status_code() && 200 !== $response->get_status_code() ) {
128
+ throw new \Exception( $response->get_status_message() );
129
+ }
130
+
131
+ return true;
132
+ }
133
+
134
+
135
+ /** Helper methods ********************************************************/
136
+
137
+
138
+ /**
139
+ * Gets a new request object.
140
+ *
141
+ * @since 3.0.0
142
+ *
143
+ * @param array $type Optional. The desired request type
144
+ * @return Payment_Gateway_Apple_Pay_API_Request the request object
145
+ */
146
+ protected function get_new_request( $type = array() ) {
147
+
148
+ return new Payment_Gateway_Apple_Pay_API_Request( $this->get_gateway() );
149
+ }
150
+
151
+
152
+ /**
153
+ * Gets the gateway instance.
154
+ *
155
+ * @since 3.0.0
156
+ *
157
+ * @return Payment_Gateway
158
+ */
159
+ protected function get_gateway() {
160
+
161
+ return $this->gateway;
162
+ }
163
+
164
+
165
+ /**
166
+ * Gets the plugin instance.
167
+ *
168
+ * @since 3.0.0
169
+ *
170
+ * @return SquareFramework\PaymentGateway\Payment_Gateway_Plugin
171
+ */
172
+ protected function get_plugin() {
173
+
174
+ return $this->get_gateway()->get_plugin();
175
+ }
176
+ }
includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api_Request.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Request API class
4
+ *
5
+ * This file defines a class used to create the Request object
6
+ * for features related to Apple Pay.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api;
14
+
15
+ use WooCommerce\Square\Framework\Api\API_JSON_Request;
16
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
17
+
18
+ defined( 'ABSPATH' ) or exit;
19
+
20
+ /**
21
+ * The Apple Pay API request object.
22
+ *
23
+ * @since 3.0.0
24
+ */
25
+ class Payment_Gateway_Apple_Pay_API_Request extends API_JSON_Request {
26
+
27
+
28
+ /** @var Payment_Gateway $gateway the gateway instance */
29
+ protected $gateway;
30
+
31
+
32
+ /**
33
+ * Constructs the request.
34
+ *
35
+ * @since 3.0.0
36
+ *
37
+ * @param Payment_Gateway $gateway the gateway instance
38
+ */
39
+ public function __construct( Payment_Gateway $gateway ) {
40
+
41
+ $this->gateway = $gateway;
42
+ }
43
+
44
+
45
+ /**
46
+ * Sets the data for merchant validation.
47
+ *
48
+ * @since 3.0.0
49
+ *
50
+ * @param string $merchant_id the merchant ID to validate
51
+ * @param string $domain_name the verified domain name
52
+ * @param string $display_name the merchant display name
53
+ */
54
+ public function set_merchant_data( $merchant_id, $domain_name, $display_name ) {
55
+
56
+ $data = array(
57
+ 'merchantIdentifier' => $merchant_id,
58
+ 'domainName' => str_replace( array( 'http://', 'https://' ), '', $domain_name ),
59
+ 'displayName' => $display_name,
60
+ );
61
+
62
+ /**
63
+ * Filters the data for merchant validation.
64
+ *
65
+ * @since 3.0.0
66
+ *
67
+ * @param array $data {
68
+ * The merchant data.
69
+ *
70
+ * @var string $merchantIdentifier the merchant ID
71
+ * @var string $domainName the verified domain name
72
+ * @var string $displayName the merchant display name
73
+ * }
74
+ * @param Payment_Gateway_Apple_Pay_API_Request the request object
75
+ */
76
+ $this->data = apply_filters( 'sv_wc_apple_pay_api_merchant_data', $data, $this );
77
+ }
78
+
79
+
80
+ /**
81
+ * Get the string representation of this response with any and all sensitive
82
+ * elements masked or removed.
83
+ *
84
+ * @since 3.0.0
85
+ * @see API_Response::to_string_safe()
86
+ *
87
+ * @return string
88
+ */
89
+ public function to_string_safe() {
90
+
91
+ // mask the merchant ID
92
+ $string = str_replace( $this->data['merchantIdentifier'], str_repeat( '*', strlen( $this->data['merchantIdentifier'] ) ), $this->to_string() );
93
+
94
+ return $string;
95
+ }
96
+ }
includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Api_Response.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Response API class
4
+ *
5
+ * This file defines a class used to create the Response object
6
+ * for features related to Apple Pay.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api;
14
+ use WooCommerce\Square\Framework\Api\API_JSON_Response;
15
+
16
+ defined( 'ABSPATH' ) or exit;
17
+
18
+ /**
19
+ * The Apple Pay API response object.
20
+ *
21
+ * @since 3.0.0
22
+ */
23
+ class Payment_Gateway_Apple_Pay_API_Response extends API_JSON_Response {
24
+
25
+
26
+ /**
27
+ * Gets the status code.
28
+ *
29
+ * @since 3.0.0
30
+ *
31
+ * @return string
32
+ */
33
+ public function get_status_code() {
34
+
35
+ return $this->statusCode;
36
+ }
37
+
38
+
39
+ /**
40
+ * Gets the status message.
41
+ *
42
+ * @since 3.0.0
43
+ *
44
+ * @return string
45
+ */
46
+ public function get_status_message() {
47
+
48
+ return $this->statusMessage;
49
+ }
50
+
51
+
52
+ /**
53
+ * Gets the validated merchant session.
54
+ *
55
+ * @since 3.0.0
56
+ *
57
+ * @return string|array
58
+ */
59
+ public function get_merchant_session() {
60
+
61
+ return $this->raw_response_json;
62
+ }
63
+
64
+
65
+ /**
66
+ * Get the string representation of this response with any and all sensitive
67
+ * elements masked or removed.
68
+ *
69
+ * No strong indication from the Apple documentation that these _need_ to be
70
+ * masked, but they don't provide any useful info and only make the debug
71
+ * logs unnecessarily huge.
72
+ *
73
+ * @since 3.0.0
74
+ * @see SquareFramework\Api\API_Response::to_string_safe()
75
+ *
76
+ * @return string
77
+ */
78
+ public function to_string_safe() {
79
+
80
+ $string = $this->to_string();
81
+
82
+ // mask the merchant session ID
83
+ $string = str_replace( $this->merchantSessionIdentifier, str_repeat( '*', 10 ), $string );
84
+
85
+ // mask the merchant ID
86
+ $string = str_replace( $this->merchantIdentifier, str_repeat( '*', 10 ), $string );
87
+
88
+ // mask the signature
89
+ $string = str_replace( $this->signature, str_repeat( '*', 10 ), $string );
90
+
91
+ return $string;
92
+ }
93
+ }
includes/Framework/PaymentGateway/ApplePay/Api/Payment_Gateway_Apple_Pay_Payment_Response.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Sync Completed Email class
4
+ *
5
+ * This file defines a class that describes Apple Pay's
6
+ * Payment Response object.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @since 3.0.0
10
+ */
11
+
12
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api;
13
+ use WooCommerce\Square\Framework\Api\API_JSON_Response;
14
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
15
+
16
+ defined( 'ABSPATH' ) or exit;
17
+
18
+ /**
19
+ * The Apple Pay payment response object.
20
+ *
21
+ * @since 3.0.0
22
+ */
23
+ class Payment_Gateway_Apple_Pay_Payment_Response extends API_JSON_Response {
24
+
25
+
26
+ /**
27
+ * Gets the authorized payment data.
28
+ *
29
+ * @since 3.0.0
30
+ *
31
+ * @return array
32
+ */
33
+ public function get_payment_data() {
34
+
35
+ return ! empty( $this->token->paymentData ) ? (array) $this->token->paymentData : array();
36
+ }
37
+
38
+
39
+ /**
40
+ * Gets the authorization transaction ID.
41
+ *
42
+ * @since 3.0.0
43
+ *
44
+ * @return string
45
+ */
46
+ public function get_transaction_id() {
47
+
48
+ return ! empty( $this->token->transactionIdentifier ) ? $this->token->transactionIdentifier : '';
49
+ }
50
+
51
+
52
+ /**
53
+ * Gets the authorized card type.
54
+ *
55
+ * @since 3.0.0
56
+ *
57
+ * @return string
58
+ */
59
+ public function get_card_type() {
60
+
61
+ $card_type = ! empty( $this->token->paymentMethod->network ) ? $this->token->paymentMethod->network : 'card';
62
+
63
+ return Payment_Gateway_Helper::normalize_card_type( $card_type );
64
+ }
65
+
66
+
67
+ /**
68
+ * Gets the last four digits of the authorized card.
69
+ *
70
+ * @since 3.0.0
71
+ *
72
+ * @return string
73
+ */
74
+ public function get_last_four() {
75
+
76
+ $last_four = '';
77
+
78
+ if ( ! empty( $this->token->paymentMethod->displayName ) ) {
79
+ $last_four = substr( $this->token->paymentMethod->displayName, -4 );
80
+ }
81
+
82
+ return $last_four;
83
+ }
84
+
85
+
86
+ /**
87
+ * Gets the billing address.
88
+ *
89
+ * @since 3.0.0
90
+ *
91
+ * @return array
92
+ */
93
+ public function get_billing_address() {
94
+
95
+ $address = ! empty( $this->response_data->billingContact ) ? $this->response_data->billingContact : null;
96
+
97
+ $billing_address = $this->prepare_address( $address );
98
+
99
+ // set the billing email
100
+ if ( ! empty( $this->response_data->shippingContact->emailAddress ) ) {
101
+ $billing_address['email'] = $this->shippingContact->emailAddress;
102
+ }
103
+
104
+ // set the billing phone number
105
+ if ( ! empty( $this->response_data->shippingContact->phoneNumber ) ) {
106
+ $billing_address['phone'] = $this->shippingContact->phoneNumber;
107
+ }
108
+
109
+ return $billing_address;
110
+ }
111
+
112
+
113
+ /**
114
+ * Gets the shipping address.
115
+ *
116
+ * @since 3.0.0
117
+ *
118
+ * @return array
119
+ */
120
+ public function get_shipping_address() {
121
+
122
+ $address = ! empty( $this->response_data->shippingContact ) ? $this->response_data->shippingContact : null;
123
+
124
+ $shipping_address = $this->prepare_address( $address );
125
+
126
+ return $shipping_address;
127
+ }
128
+
129
+
130
+ /**
131
+ * Prepare an address to WC formatting.
132
+ *
133
+ * @since 3.0.0
134
+ *
135
+ * @param \stdClass|object $contact the address to prepare
136
+ * @return array
137
+ */
138
+ protected function prepare_address( $contact ) {
139
+
140
+ $address = array(
141
+ 'first_name' => isset( $contact->givenName ) ? $contact->givenName : '',
142
+ 'last_name' => isset( $contact->familyName ) ? $contact->familyName : '',
143
+ 'address_1' => isset( $contact->addressLines[0] ) ? $contact->addressLines[0] : '',
144
+ 'address_2' => '',
145
+ 'city' => isset( $contact->locality ) ? $contact->locality : '',
146
+ 'state' => isset( $contact->administrativeArea ) ? $contact->administrativeArea : '',
147
+ 'postcode' => isset( $contact->postalCode ) ? $contact->postalCode : '',
148
+ 'country' => isset( $contact->countryCode ) ? $contact->countryCode : '',
149
+ );
150
+
151
+ if ( ! empty( $contact->addressLines[1] ) ) {
152
+ $address['address_2'] = $contact->addressLines[1];
153
+ }
154
+
155
+ $address['country'] = strtoupper( $address['country'] );
156
+
157
+ return $address;
158
+ }
159
+
160
+
161
+ /**
162
+ * Get the string representation of this response with any and all sensitive
163
+ * elements masked or removed.
164
+ *
165
+ * No strong indication from the Apple documentation that these _need_ to be
166
+ * masked, but they don't provide any useful info and only make the debug
167
+ * logs unnecessarily huge.
168
+ *
169
+ * @since 3.0.0
170
+ *
171
+ * @see WooCommerce\Square\Framework\Api\API_Response::to_string_safe()
172
+ *
173
+ * @return string
174
+ */
175
+ public function to_string_safe() {
176
+
177
+ $string = $this->to_string();
178
+
179
+ if ( ! empty( $this->token->paymentData->data ) ) {
180
+ $string = str_replace( $this->token->paymentData->data, str_repeat( '*', 10 ), $string );
181
+ }
182
+
183
+ if ( ! empty( $this->token->paymentData->signature ) ) {
184
+ $string = str_replace( $this->token->paymentData->signature, str_repeat( '*', 10 ), $string );
185
+ }
186
+
187
+ return $string;
188
+ }
189
+ }
includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay.php ADDED
@@ -0,0 +1,1029 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Payment Gateway: Apple Pay class
4
+ *
5
+ * This file defines a class that is the starting point for
6
+ * Apple Pay related features, such as Apple Pay admin settings,
7
+ * processing payments through Apple Pay, initializing classes that
8
+ * load Apple Pay related assets, etc.
9
+ *
10
+ * @package WooCommerce Square
11
+ * @subpackage Apple Pay
12
+ * @since 3.0.0
13
+ */
14
+
15
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay;
16
+ use WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api as ApplePayApi;
17
+ use WooCommerce\Square\Framework as SquareFramework;
18
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
19
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
20
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Plugin;
21
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
22
+
23
+ defined( 'ABSPATH' ) or exit;
24
+
25
+ /**
26
+ * Sets up Apple Pay support.
27
+ *
28
+ * @since 3.0.0
29
+ */
30
+ class Payment_Gateway_Apple_Pay {
31
+
32
+ /** @var Payment_Gateway_Apple_Pay_Admin the admin instance */
33
+ protected $admin;
34
+
35
+ /** @var Payment_Gateway_Apple_Pay_Frontend the frontend instance */
36
+ protected $frontend;
37
+
38
+ /** @var Payment_Gateway_Apple_Pay_AJAX the AJAX instance */
39
+ protected $ajax;
40
+
41
+ /** @var SquareFramework\PaymentGateway\Payment_Gateway_Plugin the plugin instance */
42
+ protected $plugin;
43
+
44
+ /** @var ApplePayApi\Payment_Gateway_Apple_Pay_API the Apple Pay API */
45
+ protected $api;
46
+
47
+
48
+ /**
49
+ * Constructs the class.
50
+ *
51
+ * @since 3.0.0
52
+ *
53
+ * @param Payment_Gateway_Plugin $plugin the plugin instance
54
+ */
55
+ public function __construct( Payment_Gateway_Plugin $plugin ) {
56
+
57
+ $this->plugin = $plugin;
58
+
59
+ $this->init();
60
+
61
+ if ( $this->is_available() ) {
62
+ add_filter( 'woocommerce_customer_taxable_address', array( $this, 'set_customer_taxable_address' ) );
63
+ }
64
+ }
65
+
66
+
67
+ /**
68
+ * Initializes the Apple Pay handlers.
69
+ *
70
+ * @since 3.0.0
71
+ */
72
+ protected function init() {
73
+
74
+ if ( is_admin() && ! wp_doing_ajax() ) {
75
+ $this->admin = new Payment_Gateway_Apple_Pay_Admin( $this );
76
+ } else {
77
+ $this->ajax = new Payment_Gateway_Apple_Pay_AJAX( $this );
78
+ $this->frontend = new Payment_Gateway_Apple_Pay_Frontend( $this->get_plugin(), $this );
79
+ }
80
+ }
81
+
82
+
83
+ /**
84
+ * Processes the payment after an Apple Pay authorization.
85
+ *
86
+ * This method creates a new order and calls the gateway for processing.
87
+ *
88
+ * @since 3.0.0
89
+ *
90
+ * @return array
91
+ * @throws \Exception
92
+ */
93
+ public function process_payment() {
94
+
95
+ $order = null;
96
+
97
+ try {
98
+
99
+ $payment_response = $this->get_stored_payment_response();
100
+
101
+ if ( ! $payment_response ) {
102
+ throw new \Exception( __( 'Invalid payment response data', 'woocommerce-square' ) );
103
+ }
104
+
105
+ $this->log( sprintf( esc_html__( "Payment Response:\n %s", 'woocommerce-square' ) ), $payment_response->to_string_safe() . "\n" );
106
+
107
+ $order = Payment_Gateway_Apple_Pay_Orders::create_order( WC()->cart );
108
+
109
+ $order->set_payment_method( $this->get_processing_gateway() );
110
+
111
+ // if we got to this point, the payment was authorized by Apple Pay
112
+ // from here on out, it's up to the gateway to not screw things up.
113
+ $order->add_order_note( __( 'Apple Pay payment authorized.', 'woocommerce-square' ) );
114
+
115
+ $order->set_address( $payment_response->get_billing_address(), 'billing' );
116
+ $order->set_address( $payment_response->get_shipping_address(), 'shipping' );
117
+ $order->save();
118
+
119
+ // add Apple Pay response data to the order
120
+ add_filter( 'wc_payment_gateway_' . $this->get_processing_gateway()->get_id() . '_get_order', array( $this, 'add_order_data' ) );
121
+
122
+ if ( $this->is_test_mode() ) {
123
+ $result = $this->process_test_payment( $order );
124
+ } else {
125
+ $result = $this->get_processing_gateway()->process_payment( Order_Compatibility::get_prop( $order, 'id' ) );
126
+ }
127
+
128
+ if ( isset( $result['result'] ) && 'success' !== $result['result'] ) {
129
+ throw new \Exception( __( 'Gateway processing error.', 'woocommerce-square' ) );
130
+ }
131
+
132
+ if ( $user_id = $order->get_user_id() ) {
133
+ $this->update_customer_addresses( $user_id, $payment_response );
134
+ }
135
+
136
+ $this->clear_payment_data();
137
+
138
+ return $result;
139
+
140
+ } catch ( \Exception $e ) {
141
+
142
+ if ( $order ) {
143
+
144
+ $order->add_order_note( sprintf(
145
+ /** translators: Placeholders: %s - the error message */
146
+ esc_html__( 'Apple Pay payment failed. %s', 'woocommerce-square' ),
147
+ $e->getMessage()
148
+ ) );
149
+ }
150
+
151
+ throw $e;
152
+ }
153
+ }
154
+
155
+
156
+ /**
157
+ * Updates a customer's stored billing & shipping addresses based on the
158
+ * Apple Pay payment response.
159
+ *
160
+ * @since 3.0.0
161
+ *
162
+ * @param int $user_id WordPress user ID
163
+ * @param ApplePayApi\Payment_Gateway_Apple_Pay_Payment_Response $payment_response payment response object
164
+ */
165
+ protected function update_customer_addresses( $user_id, ApplePayApi\Payment_Gateway_Apple_Pay_Payment_Response $payment_response ) {
166
+
167
+ foreach ( $payment_response->get_billing_address() as $key => $value ) {
168
+ update_user_meta( $user_id, 'billing_' . $key, $value );
169
+ }
170
+
171
+ $shipping_address = $payment_response->get_shipping_address();
172
+
173
+ if ( ! empty( $shipping_address['address_1'] ) ) {
174
+
175
+ foreach ( $payment_response->get_shipping_address() as $key => $value ) {
176
+ update_user_meta( $user_id, 'shipping_' . $key, $value );
177
+ }
178
+ }
179
+ }
180
+
181
+
182
+ /**
183
+ * Simulates a successful gateway payment response.
184
+ *
185
+ * This provides an easy way for merchants to test that their certificates
186
+ * and other settings are correctly configured and communicating with Apple
187
+ * without processing actual payments to test.
188
+ *
189
+ * @since 3.0.0
190
+ *
191
+ * @param \WC_Order $order order object
192
+ * @return array
193
+ */
194
+ protected function process_test_payment( \WC_Order $order ) {
195
+
196
+ $order->payment_complete();
197
+
198
+ WC()->cart->empty_cart();
199
+
200
+ return array(
201
+ 'result' => 'success',
202
+ 'redirect' => $this->get_processing_gateway()->get_return_url( $order ),
203
+ );
204
+ }
205
+
206
+
207
+ /**
208
+ * Gets a single product payment request.
209
+ *
210
+ * @since 3.0.0
211
+ * @see Payment_Gateway_Apple_Pay::build_payment_request()
212
+ *
213
+ * @param \WC_Product $product product object
214
+ * @param bool $in_cart whether to generate a cart for this request
215
+ * @return array
216
+ * @throws \Exception
217
+ */
218
+ public function get_product_payment_request( \WC_Product $product, $in_cart = false ) {
219
+
220
+ if ( ! is_user_logged_in() ) {
221
+ WC()->session->set_customer_session_cookie( true );
222
+ }
223
+
224
+ // no subscription products
225
+ if ( $this->get_plugin()->is_subscriptions_active() && \WC_Subscriptions_Product::is_subscription( $product ) ) {
226
+ throw new \Exception( __( 'Not available for subscription products.', 'woocommerce-square' ) );
227
+ }
228
+
229
+ // no pre-order "charge upon release" products
230
+ if ( $this->get_plugin()->is_pre_orders_active() && \WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
231
+ throw new \Exception( __( 'Not available for pre-order products that are set to charge upon release.', 'woocommerce-square' ) );
232
+ }
233
+
234
+ // only simple products
235
+ if ( ! $product->is_type( 'simple' ) ) {
236
+ throw new \Exception( __( 'Buy Now is only available for simple products', 'woocommerce-square' ) );
237
+ }
238
+
239
+ // if this product can't be purchased, bail
240
+ if ( ! $product->is_purchasable() || ! $product->is_in_stock() || ! $product->has_enough_stock( 1 ) ) {
241
+ throw new \Exception( __( 'Product is not available for purchase.', 'woocommerce-square' ) );
242
+ }
243
+
244
+ if ( $in_cart ) {
245
+
246
+ WC()->cart->empty_cart();
247
+
248
+ WC()->cart->add_to_cart( $product->get_id() );
249
+
250
+ $request = $this->get_cart_payment_request( WC()->cart );
251
+
252
+ } else {
253
+
254
+ $request = $this->build_payment_request( $product->get_price(), array( 'needs_shipping' => $product->needs_shipping() ) );
255
+
256
+ $stored_request = $this->get_stored_payment_request();
257
+
258
+ $stored_request['product_id'] = $product->get_id();
259
+
260
+ $this->store_payment_request( $stored_request );
261
+ }
262
+
263
+ /**
264
+ * Filters the Apple Pay Buy Now JS payment request.
265
+ *
266
+ * @since 3.0.0
267
+ * @param array $request request data
268
+ * @param \WC_Product $product product object
269
+ */
270
+ return apply_filters( 'sv_wc_apple_pay_buy_now_payment_request', $request, $product );
271
+ }
272
+
273
+
274
+ /**
275
+ * Gets a payment request based on WooCommerce cart data.
276
+ *
277
+ * @since 3.0.0
278
+ * @see Payment_Gateway_Apple_Pay::build_payment_request()
279
+ *
280
+ * @param \WC_Cart $cart cart object
281
+ * @return array
282
+ * @throws \Exception
283
+ */
284
+ public function get_cart_payment_request( \WC_Cart $cart ) {
285
+
286
+ if ( $this->get_plugin()->is_subscriptions_active() && \WC_Subscriptions_Cart::cart_contains_subscription() ) {
287
+ throw new \Exception( __( 'Cart contains subscriptions.', 'woocommerce-square' ) );
288
+ }
289
+
290
+ if ( $this->get_plugin()->is_pre_orders_active() && \WC_Pre_Orders_Cart::cart_contains_pre_order() ) {
291
+ throw new \Exception( __( 'Cart contains pre-orders.', 'woocommerce-square' ) );
292
+ }
293
+
294
+ if ( Plugin_Compatibility::is_wc_version_lt( '3.2' ) && ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
295
+ define( 'WOOCOMMERCE_CHECKOUT', true );
296
+ }
297
+
298
+ $cart->calculate_totals();
299
+
300
+ if ( count( WC()->shipping->get_packages() ) > 1 ) {
301
+ throw new \Exception( __( 'Apple Pay cannot be used for multiple shipments.', 'woocommerce-square' ) );
302
+ }
303
+
304
+ $args = array(
305
+ 'line_totals' => $this->get_cart_totals( $cart ),
306
+ 'needs_shipping' => $cart->needs_shipping(),
307
+ );
308
+
309
+ // build it!
310
+ $request = $this->build_payment_request( $cart->total, $args );
311
+
312
+ /**
313
+ * Filters the Apple Pay cart JS payment request.
314
+ *
315
+ * @since 3.0.0
316
+ * @param array $args the cart JS payment request
317
+ * @param \WC_Cart $cart the cart object
318
+ */
319
+ return apply_filters( 'sv_wc_apple_pay_cart_payment_request', $request, $cart );
320
+ }
321
+
322
+
323
+ /**
324
+ * Recalculates the lines and totals for the current payment request.
325
+ *
326
+ * @since 3.0.0
327
+ *
328
+ * @return array
329
+ * @throws \Exception
330
+ */
331
+ public function recalculate_totals() {
332
+
333
+ $payment_request = $this->get_stored_payment_request();
334
+
335
+ if ( empty( $payment_request ) ){
336
+ throw new \Exception( __( 'Payment request data is missing.', 'woocommerce-square' ) );
337
+ }
338
+
339
+ // if this is a single product request, make sure the cart gets populated
340
+ if ( ! empty( $payment_request['product_id'] ) && $product = wc_get_product( $payment_request['product_id'] ) ) {
341
+ $payment_request = $this->get_product_payment_request( $product, true );
342
+ }
343
+
344
+ if ( ! WC()->cart ) {
345
+ throw new \Exception( __( 'Cart data is missing.', 'woocommerce-square' ) );
346
+ }
347
+
348
+ $totals = $this->get_cart_totals( WC()->cart );
349
+
350
+ $payment_request['lineItems'] = $this->build_payment_request_lines( $totals );
351
+ $payment_request['shippingMethods'] = array();
352
+
353
+ $packages = WC()->shipping->get_packages();
354
+
355
+ if ( ! empty( $packages ) ) {
356
+
357
+ foreach ( $packages[0]['rates'] as $method ) {
358
+
359
+ /**
360
+ * Filters a shipping method's description for the Apple Pay payment card.
361
+ *
362
+ * @since 3.0.0
363
+ *
364
+ * @param string $detail shipping method detail, such as delivery estimation
365
+ * @param object $method shipping method object
366
+ */
367
+ $method_detail = apply_filters( 'wc_payment_gateway_apple_pay_shipping_method_detail', '', $method );
368
+
369
+ $payment_request['shippingMethods'][] = array(
370
+ 'label' => $method->get_label(),
371
+ 'detail' => $method_detail,
372
+ 'amount' => $this->format_price( $method->cost ),
373
+ 'identifier' => $method->id,
374
+ );
375
+ }
376
+ }
377
+
378
+ // reset the order total based on the new line items
379
+ $payment_request['total']['amount'] = $this->format_price( array_sum( wp_list_pluck( $payment_request['lineItems'], 'amount' ) ) );
380
+
381
+ // update the stored payment request session with the new line items & totals
382
+ $this->store_payment_request( $payment_request );
383
+
384
+ return $payment_request;
385
+ }
386
+
387
+
388
+ /**
389
+ * Gets the line totals for a cart.
390
+ *
391
+ * @since 3.0.0
392
+ * @see Payment_Gateway_Apple_Pay::build_payment_request_lines()
393
+ *
394
+ * @param \WC_Cart $cart cart object
395
+ * @return array
396
+ */
397
+ protected function get_cart_totals( \WC_Cart $cart ) {
398
+
399
+ if ( Plugin_Compatibility::is_wc_version_lt( '3.2' ) && ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
400
+ define( 'WOOCOMMERCE_CHECKOUT', true );
401
+ }
402
+
403
+ $cart->calculate_totals();
404
+
405
+ return array(
406
+ 'subtotal' => $cart->subtotal_ex_tax,
407
+ 'discount' => $cart->get_cart_discount_total(),
408
+ 'shipping' => $cart->shipping_total,
409
+ 'fees' => $cart->fee_total,
410
+ 'taxes' => $cart->tax_total + $cart->shipping_tax_total,
411
+ );
412
+ }
413
+
414
+
415
+ /**
416
+ * Builds a payment request for the Apple Pay JS.
417
+ *
418
+ * This contains all of the data necessary to complete a payment.
419
+ *
420
+ * @since 3.0.0
421
+ *
422
+ * @param float|int $amount amount to be charged by Apple Pay
423
+ * @param array $args {
424
+ * Optional. The payment request args.
425
+ *
426
+ * @type string $currency_code Payment currency code. Defaults to the shop currency.
427
+ * @type string $country_code Payment country code. Defaults to the shop base country.
428
+ * @type string $merchant_name Merchant name. Defaults to the shop name.
429
+ * @type array $merchant_capabilities merchant capabilities
430
+ * @type array $supported_networks supported networks or card types
431
+ * @type bool $needs_shipping whether the payment needs shipping
432
+ * @type array $line_totals request line totals. @see \Payment_Gateway_Apple_Pay::build_payment_request_lines()
433
+ * }
434
+ *
435
+ * @return array
436
+ */
437
+ public function build_payment_request( $amount, $args = array() ) {
438
+
439
+ $args = wp_parse_args( $args, array(
440
+ 'currency_code' => get_woocommerce_currency(),
441
+ 'country_code' => get_option( 'woocommerce_default_country' ),
442
+ 'merchant_name' => get_bloginfo( 'name', 'display' ),
443
+ 'merchant_capabilities' => $this->get_capabilities(),
444
+ 'supported_networks' => $this->get_supported_networks(),
445
+ 'line_totals' => array(),
446
+ 'needs_shipping' => false,
447
+ ) );
448
+
449
+ // set the base required defaults
450
+ $request = array(
451
+ 'currencyCode' => $args['currency_code'],
452
+ 'countryCode' => substr( $args['country_code'], 0, 2 ),
453
+ 'merchantCapabilities' => $args['merchant_capabilities'],
454
+ 'supportedNetworks' => $args['supported_networks'],
455
+ 'requiredBillingContactFields' => array( 'postalAddress' ),
456
+ 'requiredShippingContactFields' => array(
457
+ 'phone',
458
+ 'email',
459
+ 'name',
460
+ ),
461
+ );
462
+
463
+ if ( $args['needs_shipping'] ) {
464
+ $request['requiredShippingContactFields'][] = 'postalAddress';
465
+ }
466
+
467
+ if ( is_array( $args['line_totals'] ) && ! empty( $args['line_totals'] ) ) {
468
+ $request['lineItems'] = $this->build_payment_request_lines( $args['line_totals'] );
469
+ }
470
+
471
+ // order total
472
+ $request['total'] = array(
473
+ 'type' => 'final',
474
+ 'label' => $args['merchant_name'],
475
+ 'amount' => $this->format_price( $amount ),
476
+ );
477
+
478
+ $this->store_payment_request( $request );
479
+
480
+ // remove line item keys that are only useful for us later
481
+ if ( ! empty( $request['lineItems'] ) ) {
482
+ $request['lineItems'] = array_values( $request['lineItems'] );
483
+ }
484
+
485
+ return $request;
486
+ }
487
+
488
+
489
+ /**
490
+ * Builds payment request lines for the Apple Pay JS.
491
+ *
492
+ * Apple guidelines prefer that the "lines" displayed on the Apple Pay card
493
+ * should be overall order totals, instead of listing actual product lines.
494
+ * This method standardizes the main breakdowns which are:
495
+ * + Subtotal
496
+ * + Discounts (represented as a single negative amount)
497
+ * + Shipping
498
+ * + Fees
499
+ * + Taxes
500
+ *
501
+ * @since 3.0.0
502
+ *
503
+ * @param array $totals {
504
+ * Payment line totals.
505
+ *
506
+ * @type float $subtotal items subtotal
507
+ * @type float $discount discounts total
508
+ * @type float $shipping shipping total
509
+ * @type float $fees fees total
510
+ * @type float $taxes tax total
511
+ * }
512
+ * @return array
513
+ */
514
+ public function build_payment_request_lines( $totals ) {
515
+
516
+ $totals = wp_parse_args( $totals, array(
517
+ 'subtotal' => 0.00,
518
+ 'discount' => 0.00,
519
+ 'shipping' => 0.00,
520
+ 'fees' => 0.00,
521
+ 'taxes' => 0.00,
522
+ ) );
523
+
524
+ $lines = array();
525
+
526
+ // subtotal
527
+ if ( $totals['subtotal'] > 0 ) {
528
+
529
+ $lines['subtotal'] = array(
530
+ 'type' => 'final',
531
+ 'label' => __( 'Subtotal', 'woocommerce-square' ),
532
+ 'amount' => $this->format_price( $totals['subtotal'] ),
533
+ );
534
+ }
535
+
536
+ // discounts
537
+ if ( $totals['discount'] > 0 ) {
538
+
539
+ $lines['discount'] = array(
540
+ 'type' => 'final',
541
+ 'label' => __( 'Discount', 'woocommerce-square' ),
542
+ 'amount' => abs( $this->format_price( $totals['discount'] ) ) * -1,
543
+ );
544
+ }
545
+
546
+ // shipping
547
+ if ( $totals['shipping'] > 0 ) {
548
+
549
+ $lines['shipping'] = array(
550
+ 'type' => 'final',
551
+ 'label' => __( 'Shipping', 'woocommerce-square' ),
552
+ 'amount' => $this->format_price( $totals['shipping'] ),
553
+ );
554
+ }
555
+
556
+ // fees
557
+ if ( $totals['fees'] > 0 ) {
558
+
559
+ $lines['fees'] = array(
560
+ 'type' => 'final',
561
+ 'label' => __( 'Fees', 'woocommerce-square' ),
562
+ 'amount' => $this->format_price( $totals['fees'] ),
563
+ );
564
+ }
565
+
566
+ // taxes
567
+ if ( $totals['taxes'] > 0 ) {
568
+
569
+ $lines['taxes'] = array(
570
+ 'type' => 'final',
571
+ 'label' => __( 'Taxes', 'woocommerce-square' ),
572
+ 'amount' => $this->format_price( $totals['taxes'] ),
573
+ );
574
+ }
575
+
576
+ return $lines;
577
+ }
578
+
579
+
580
+ /**
581
+ * Formats a total price for use with Apple Pay JS.
582
+ *
583
+ * @since 3.0.0
584
+ *
585
+ * @param string|float $price the price to format
586
+ * @return string
587
+ */
588
+ protected function format_price( $price ) {
589
+
590
+ return wc_format_decimal( $price, 2 );
591
+ }
592
+
593
+
594
+ /**
595
+ * Gets the stored payment request data.
596
+ *
597
+ * @since 3.0.0
598
+ *
599
+ * @return array
600
+ */
601
+ public function get_stored_payment_request() {
602
+
603
+ return WC()->session->get( 'apple_pay_payment_request', array() );
604
+ }
605
+
606
+
607
+ /**
608
+ * Gets the stored payment response data.
609
+ *
610
+ * @since 3.0.0
611
+ *
612
+ * @return false|ApplePayApi\Payment_Gateway_Apple_Pay_Payment_Response|false
613
+ */
614
+ public function get_stored_payment_response() {
615
+
616
+ $response_data = WC()->session->get( 'apple_pay_payment_response', array() );
617
+
618
+ if ( ! empty( $response_data ) ) {
619
+ return new ApplePayApi\Payment_Gateway_Apple_Pay_Payment_Response( $response_data );
620
+ } else {
621
+ return false;
622
+ }
623
+ }
624
+
625
+
626
+ /**
627
+ * Stores payment request data for later use.
628
+ *
629
+ * @since 3.0.0
630
+ *
631
+ * @param mixed|array $data
632
+ */
633
+ public function store_payment_request( $data ) {
634
+
635
+ WC()->session->set( 'apple_pay_payment_request', $data );
636
+ }
637
+
638
+
639
+ /**
640
+ * Stores payment response data for later use.
641
+ *
642
+ * @since 3.0.0
643
+ *
644
+ * @param mixed|array $data
645
+ */
646
+ public function store_payment_response( $data ) {
647
+
648
+ WC()->session->set( 'apple_pay_payment_response', $data );
649
+ }
650
+
651
+
652
+ /**
653
+ * Clears all payment request & response data from the session.
654
+ *
655
+ * @since 3.0.0
656
+ */
657
+ public function clear_payment_data() {
658
+
659
+ unset( WC()->session->apple_pay_payment_request );
660
+ unset( WC()->session->apple_pay_payment_response );
661
+ unset( WC()->session->order_awaiting_payment );
662
+ }
663
+
664
+
665
+ /**
666
+ * Filters and sets the customer's taxable address.
667
+ *
668
+ * This is necessary because Apple Pay doesn't ever provide a billing
669
+ * address until after payment is complete. If the shop is set to calculate
670
+ * tax based on the billing address, we need to use the shipping address
671
+ * to at least get some rates for new customers.
672
+ *
673
+ * @internal
674
+ *
675
+ * @since 3.0.0
676
+ *
677
+ * @param array $address taxable address
678
+ * @return array
679
+ */
680
+ public function set_customer_taxable_address( $address ) {
681
+
682
+ $billing_country = WC()->customer->get_billing_country();
683
+
684
+ // set to the shipping address provided by Apple Pay if:
685
+ // 1. shipping is available
686
+ // 2. billing is not available
687
+ // 3. taxes aren't configured to use the shop base
688
+ if ( WC()->customer->get_shipping_country() && ! $billing_country && $address[0] !== WC()->countries->get_base_country() ) {
689
+
690
+ $address = array(
691
+ WC()->customer->get_shipping_country(),
692
+ WC()->customer->get_shipping_state(),
693
+ WC()->customer->get_shipping_postcode(),
694
+ WC()->customer->get_shipping_city(),
695
+ );
696
+ }
697
+
698
+ return $address;
699
+ }
700
+
701
+
702
+ /**
703
+ * Allows the processing gateway to add Apple Pay details to the payment data.
704
+ *
705
+ * @internal
706
+ *
707
+ * @since 3.0.0
708
+ *
709
+ * @param \WC_Order $order the order object
710
+ * @return \WC_Order
711
+ */
712
+ public function add_order_data( $order ) {
713
+
714
+ if ( $response = $this->get_stored_payment_response() ) {
715
+ $order = $this->get_processing_gateway()->get_order_for_apple_pay( $order, $response );
716
+ }
717
+
718
+ return $order;
719
+ }
720
+
721
+
722
+ /**
723
+ * Gets the Apple Pay API.
724
+ *
725
+ * @since 3.0.0
726
+ *
727
+ * @return Payment_Gateway_Apple_Pay_API
728
+ */
729
+ public function get_api() {
730
+
731
+ if ( ! $this->api instanceof ApplePayApi\Payment_Gateway_Apple_Pay_API ) {
732
+
733
+ require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api.php');
734
+ require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-request.php');
735
+ require_once( $this->get_plugin()->get_payment_gateway_framework_path() . '/apple-pay/api/class-sv-wc-payment-gateway-apple-pay-api-response.php');
736
+
737
+ $this->api = new ApplePayApi\Payment_Gateway_Apple_Pay_API( $this->get_processing_gateway() );
738
+ }
739
+
740
+ return $this->api;
741
+ }
742
+
743
+
744
+ /**
745
+ * Adds a log entry to the gateway's debug log.
746
+ *
747
+ * @since 3.0.0
748
+ *
749
+ * @param string $message the log message to add
750
+ */
751
+ public function log( $message ) {
752
+
753
+ $gateway = $this->get_processing_gateway();
754
+
755
+ if ( ! $gateway ) {
756
+ return;
757
+ }
758
+
759
+ if ( $gateway->debug_log() ) {
760
+ $gateway->get_plugin()->log( sprintf( '[Apple Pay] %s', $message ), $gateway->get_id() );
761
+ }
762
+ }
763
+
764
+
765
+ /**
766
+ * Determines if Apple Pay is available.
767
+ *
768
+ * This does not indicate browser support or a user's ability, but rather
769
+ * that Apple Pay is properly configured and ready to be initiated by the
770
+ * Apple Pay JS.
771
+ *
772
+ * @since 3.0.0
773
+ *
774
+ * @return bool
775
+ */
776
+ public function is_available() {
777
+
778
+ $is_available = wc_site_is_https() && $this->is_configured();
779
+
780
+ $is_available = $is_available && in_array( get_woocommerce_currency(), $this->get_accepted_currencies(), true );
781
+
782
+ /**
783
+ * Filters whether Apple Pay should be made available to users.
784
+ *
785
+ * @since 3.0.0
786
+ * @param bool $is_available
787
+ */
788
+ return apply_filters( 'sv_wc_apple_pay_is_available', $is_available );
789
+ }
790
+
791
+
792
+ /**
793
+ * Determines if Apple Pay settings are properly configured.
794
+ *
795
+ * @since 3.0.0
796
+ *
797
+ * @return bool
798
+ */
799
+ public function is_configured() {
800
+
801
+ if ( ! $this->get_processing_gateway() ) {
802
+ return false;
803
+ }
804
+
805
+ $is_configured = $this->is_enabled() && $this->get_merchant_id() && $this->get_processing_gateway()->is_enabled();
806
+
807
+ $is_configured = $is_configured && $this->is_cert_configured();
808
+
809
+ return $is_configured;
810
+ }
811
+
812
+
813
+ /**
814
+ * Determines if the certification path is set and valid.
815
+ *
816
+ * @since 3.0.0
817
+ *
818
+ * @return bool
819
+ */
820
+ public function is_cert_configured() {
821
+
822
+ return is_readable( $this->get_cert_path() );
823
+ }
824
+
825
+
826
+ /**
827
+ * Determines if Apple Pay is enabled.
828
+ *
829
+ * @since 3.0.0
830
+ *
831
+ * @return bool
832
+ */
833
+ public function is_enabled() {
834
+
835
+ return 'yes' === get_option( 'sv_wc_apple_pay_enabled' );
836
+ }
837
+
838
+
839
+ /**
840
+ * Determines if test mode is enabled.
841
+ *
842
+ * @since 3.0.0
843
+ *
844
+ * @return bool
845
+ */
846
+ public function is_test_mode() {
847
+
848
+ return 'yes' === get_option( 'sv_wc_apple_pay_test_mode' );
849
+ }
850
+
851
+
852
+ /**
853
+ * Gets the configured Apple merchant ID.
854
+ *
855
+ * @since 3.0.0
856
+ * @return string
857
+ */
858
+ public function get_merchant_id() {
859
+
860
+ return get_option( 'sv_wc_apple_pay_merchant_id' );
861
+ }
862
+
863
+
864
+ /**
865
+ * Gets the certificate file path.
866
+ *
867
+ * @since 3.0.0
868
+ *
869
+ * @return string
870
+ */
871
+ public function get_cert_path() {
872
+
873
+ return get_option( 'sv_wc_apple_pay_cert_path' );
874
+ }
875
+
876
+
877
+ /**
878
+ * Gets the currencies accepted by the gateway's Apple Pay integration.
879
+ *
880
+ * @since 3.0.0
881
+ *
882
+ * @return array
883
+ */
884
+ public function get_accepted_currencies() {
885
+
886
+ $currencies = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_apple_pay_currencies() : array();
887
+
888
+ /**
889
+ * Filters the currencies accepted by the gateway's Apple Pay integration.
890
+ *
891
+ * @since 3.0.0
892
+ * @return array
893
+ */
894
+ return apply_filters( 'sv_wc_apple_pay_accepted_currencies', $currencies );
895
+ }
896
+
897
+
898
+ /**
899
+ * Gets the gateway's Apple Pay capabilities.
900
+ *
901
+ * @since 3.0.0
902
+ *
903
+ * @return array
904
+ */
905
+ public function get_capabilities() {
906
+
907
+ $valid_capabilities = array(
908
+ 'supports3DS',
909
+ 'supportsEMV',
910
+ 'supportsCredit',
911
+ 'supportsDebit',
912
+ );
913
+
914
+ $gateway_capabilities = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_apple_pay_capabilities() : array();
915
+
916
+ $capabilities = array_intersect( $valid_capabilities, $gateway_capabilities );
917
+
918
+ /**
919
+ * Filters the gateway's Apple Pay capabilities.
920
+ *
921
+ * @since 3.0.0
922
+ *
923
+ * @param array $capabilities the gateway capabilities
924
+ * @param SquareFramework\PaymentGateway\ApplePay\Payment_Gateway_Apple_Pay $handler the Apple Pay handler
925
+ */
926
+ return apply_filters( 'sv_wc_apple_pay_capabilities', array_values( $capabilities ), $this );
927
+ }
928
+
929
+
930
+ /**
931
+ * Gets the supported networks for Apple Pay.
932
+ *
933
+ * @since 3.0.0
934
+ *
935
+ * @return array
936
+ */
937
+ public function get_supported_networks() {
938
+
939
+ $accepted_card_types = ( $this->get_processing_gateway() ) ? $this->get_processing_gateway()->get_card_types() : array();
940
+
941
+ $accepted_card_types = array_map( '\\WooCommerce\\Square\\Framework\\PaymentGateway\\Payment_Gateway_Helper::normalize_card_type', $accepted_card_types );
942
+
943
+ $valid_networks = array(
944
+ Payment_Gateway_Helper::CARD_TYPE_AMEX => 'amex',
945
+ Payment_Gateway_Helper::CARD_TYPE_DISCOVER => 'discover',
946
+ Payment_Gateway_Helper::CARD_TYPE_MASTERCARD => 'masterCard',
947
+ Payment_Gateway_Helper::CARD_TYPE_VISA => 'visa',
948
+ 'privateLabel' => 'privateLabel', // ?
949
+ );
950
+
951
+ $networks = array_intersect_key( $valid_networks, array_flip( $accepted_card_types ) );
952
+
953
+ /**
954
+ * Filters the supported Apple Pay networks (card types).
955
+ *
956
+ * @since 3.0.0
957
+ *
958
+ * @param array $networks the supported networks
959
+ * @param SquareFramework\PaymentGateway\ApplePay\Payment_Gateway_Apple_Pay $handler the Apple Pay handler
960
+ */
961
+ return apply_filters( 'sv_wc_apple_pay_supported_networks', array_values( $networks ), $this );
962
+ }
963
+
964
+
965
+ /**
966
+ * Gets the gateways that declare Apple Pay support.
967
+ *
968
+ * @since 3.0.0
969
+ *
970
+ * @return array the supporting gateways as `$gateway_id => Payment_Gateway`
971
+ */
972
+ public function get_supporting_gateways() {
973
+
974
+ $available_gateways = $this->get_plugin()->get_gateways();
975
+ $supporting_gateways = array();
976
+
977
+ foreach ( $available_gateways as $key => $gateway ) {
978
+
979
+ if ( $gateway->supports_apple_pay() ) {
980
+ $supporting_gateways[ $gateway->get_id() ] = $gateway;
981
+ }
982
+ }
983
+
984
+ return $supporting_gateways;
985
+ }
986
+
987
+
988
+ /**
989
+ * Gets the gateway set to process Apple Pay transactions.
990
+ *
991
+ * @since 3.0.0
992
+ *
993
+ * @return SquareFramework\PaymentGateway\Payment_Gateway|null
994
+ */
995
+ public function get_processing_gateway() {
996
+
997
+ $gateways = $this->get_supporting_gateways();
998
+
999
+ $gateway_id = get_option( 'sv_wc_apple_pay_payment_gateway' );
1000
+
1001
+ return isset( $gateways[ $gateway_id ] ) ? $gateways[ $gateway_id ] : null;
1002
+ }
1003
+
1004
+
1005
+ /**
1006
+ * Gets the Apple Pay button style.
1007
+ *
1008
+ * @since 3.0.0
1009
+ *
1010
+ * @return string
1011
+ */
1012
+ public function get_button_style() {
1013
+
1014
+ return get_option( 'sv_wc_apple_pay_button_style', 'black' );
1015
+ }
1016
+
1017
+
1018
+ /**
1019
+ * Gets the gateway plugin instance.
1020
+ *
1021
+ * @since 3.0.0
1022
+ *
1023
+ * @return Payment_Gateway_Plugin
1024
+ */
1025
+ public function get_plugin() {
1026
+
1027
+ return $this->plugin;
1028
+ }
1029
+ }
includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Admin.php ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Admin class
4
+ *
5
+ * This file defines a class that adds admin settings related
6
+ * to Apply Pay.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay;
14
+
15
+ use WooCommerce\Square\Framework\Square_Helper;
16
+
17
+ defined( 'ABSPATH' ) or exit;
18
+
19
+ /**
20
+ * Sets up the Apple Pay settings screen.
21
+ *
22
+ * @since 3.0.0
23
+ */
24
+ class Payment_Gateway_Apple_Pay_Admin {
25
+
26
+
27
+ /** @var Payment_Gateway_Apple_Pay the Apple Pay handler instance */
28
+ protected $handler;
29
+
30
+
31
+ /**
32
+ * Construct the class.
33
+ *
34
+ * @since 3.0.0
35
+ *
36
+ * @param Payment_Gateway_Apple_Pay $handler main Apple Pay handler instance
37
+ */
38
+ public function __construct( $handler ) {
39
+
40
+ $this->handler = $handler;
41
+
42
+ // add Apple Pay to the checkout settings sections
43
+ add_filter( 'woocommerce_get_sections_checkout', array( $this, 'add_settings_section' ), 99 );
44
+
45
+ // output the settings
46
+ add_action( 'woocommerce_settings_checkout', array( $this, 'add_settings' ) );
47
+
48
+ // render the special "static" gateway select
49
+ add_action( 'woocommerce_admin_field_static', array( $this, 'render_static_setting' ) );
50
+
51
+ // save the settings
52
+ add_action( 'woocommerce_settings_save_checkout', array( $this, 'save_settings' ) );
53
+
54
+ // add admin notices for configuration options that need attention
55
+ add_action( 'admin_footer', array( $this, 'add_admin_notices' ), 10 );
56
+ }
57
+
58
+
59
+ /**
60
+ * Adds Apple Pay to the checkout settings sections.
61
+ *
62
+ * @internal
63
+ *
64
+ * @since 3.0.0
65
+ *
66
+ * @param array $sections the existing sections
67
+ * @return array
68
+ */
69
+ public function add_settings_section( $sections ) {
70
+
71
+ $sections['apple-pay'] = __( 'Apple Pay', 'woocommerce-square' );
72
+
73
+ return $sections;
74
+ }
75
+
76
+
77
+ /**
78
+ * Gets all of the combined settings.
79
+ *
80
+ * @since 3.0.0
81
+ *
82
+ * @return array $settings The combined settings.
83
+ */
84
+ public function get_settings() {
85
+
86
+ $settings = array(
87
+
88
+ array(
89
+ 'title' => __( 'Apple Pay', 'woocommerce-square' ),
90
+ 'type' => 'title',
91
+ ),
92
+
93
+ array(
94
+ 'id' => 'sv_wc_apple_pay_enabled',
95
+ 'title' => __( 'Enable / Disable', 'woocommerce-square' ),
96
+ 'desc' => __( 'Accept Apple Pay', 'woocommerce-square' ),
97
+ 'type' => 'checkbox',
98
+ 'default' => 'no',
99
+ ),
100
+
101
+ array(
102
+ 'id' => 'sv_wc_apple_pay_display_locations',
103
+ 'title' => __( 'Allow Apple Pay on', 'woocommerce-square' ),
104
+ 'type' => 'multiselect',
105
+ 'class' => 'wc-enhanced-select',
106
+ 'css' => 'width: 350px;',
107
+ 'options' => $this->get_display_location_options(),
108
+ 'default' => array_keys( $this->get_display_location_options() ),
109
+ ),
110
+
111
+ array(
112
+ 'id' => 'sv_wc_apple_pay_button_style',
113
+ 'title' => __( 'Button Style', 'woocommerce-square' ),
114
+ 'type' => 'select',
115
+ 'options' => array(
116
+ 'black' => __( 'Black', 'woocommerce-square' ),
117
+ 'white' => __( 'White', 'woocommerce-square' ),
118
+ 'white-with-line' => __( 'White with outline', 'woocommerce-square' ),
119
+ ),
120
+ 'default' => 'black',
121
+ ),
122
+
123
+ array(
124
+ 'type' => 'sectionend',
125
+ ),
126
+ );
127
+
128
+ $connection_settings = array(
129
+ array(
130
+ 'title' => __( 'Connection Settings', 'woocommerce-square' ),
131
+ 'type' => 'title',
132
+ ),
133
+
134
+ array(
135
+ 'id' => 'sv_wc_apple_pay_merchant_id',
136
+ 'title' => __( 'Apple Merchant ID', 'woocommerce-square' ),
137
+ 'type' => 'text',
138
+ 'desc' => sprintf(
139
+ /** translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
140
+ __( 'This is found in your %1$sApple developer account%2$s', 'woocommerce-square' ),
141
+ '<a href="https://developer.apple.com" target="_blank">', '</a>'
142
+ ),
143
+ ),
144
+
145
+ array(
146
+ 'id' => 'sv_wc_apple_pay_cert_path',
147
+ 'title' => __( 'Certificate Path', 'woocommerce-square' ),
148
+ 'type' => 'text',
149
+ 'desc_tip' => __( 'The full system path to your certificate file from Apple. For security reasons you should store this outside of your web root.', 'woocommerce-square' ),
150
+ 'desc' => sprintf(
151
+ /* translators: Placeholders: %s - the server's web root path */
152
+ __( 'For reference, your current web root path is: %s', 'woocommerce-square' ),
153
+ '<code>' . ABSPATH . '</code>'
154
+ ),
155
+ ),
156
+ );
157
+
158
+ $gateway_setting_id = 'sv_wc_apple_pay_payment_gateway';
159
+ $gateway_options = $this->get_gateway_options();
160
+
161
+ if ( 1 === count( $gateway_options ) ) {
162
+
163
+ $connection_settings[] = array(
164
+ 'id' => $gateway_setting_id,
165
+ 'title' => __( 'Processing Gateway', 'woocommerce-square' ),
166
+ 'type' => 'static',
167
+ 'value' => key( $gateway_options ),
168
+ 'label' => current( $gateway_options ),
169
+ );
170
+
171
+ } else {
172
+
173
+ $connection_settings[] = array(
174
+ 'id' => $gateway_setting_id,
175
+ 'title' => __( 'Processing Gateway', 'woocommerce-square' ),
176
+ 'type' => 'select',
177
+ 'options' => $this->get_gateway_options(),
178
+ );
179
+ }
180
+
181
+ $connection_settings[] = array(
182
+ 'id' => 'sv_wc_apple_pay_test_mode',
183
+ 'title' => __( 'Test Mode', 'woocommerce-square' ),
184
+ 'desc' => __( 'Enable to test Apple Pay functionality throughout your sites without processing real payments.', 'woocommerce-square' ),
185
+ 'type' => 'checkbox',
186
+ 'default' => 'no',
187
+ );
188
+
189
+ $connection_settings[] = array(
190
+ 'type' => 'sectionend',
191
+ );
192
+
193
+ $settings = array_merge( $settings, $connection_settings );
194
+
195
+ /**
196
+ * Filter the combined settings.
197
+ *
198
+ * @since 3.0.0
199
+ * @param array $settings The combined settings.
200
+ */
201
+ return apply_filters( 'woocommerce_get_settings_apple_pay', $settings );
202
+ }
203
+
204
+
205
+ /**
206
+ * Outputs the settings fields.
207
+ *
208
+ * @internal
209
+ *
210
+ * @since 3.0.0
211
+ */
212
+ public function add_settings() {
213
+ global $current_section;
214
+
215
+ if ( 'apple-pay' === $current_section ) {
216
+ \WC_Admin_Settings::output_fields( $this->get_settings() );
217
+ }
218
+ }
219
+
220
+
221
+ /**
222
+ * Saves the settings.
223
+ *
224
+ * @internal
225
+ *
226
+ * @since 3.0.0
227
+ *
228
+ * @global string $current_section The current settings section.
229
+ */
230
+ public function save_settings() {
231
+ global $current_section;
232
+
233
+ // Output the general settings
234
+ if ( 'apple-pay' == $current_section ) {
235
+
236
+ \WC_Admin_Settings::save_fields( $this->get_settings() );
237
+ }
238
+ }
239
+
240
+
241
+ /**
242
+ * Renders a static setting.
243
+ *
244
+ * This "setting" just displays simple text instead of a <select> with only
245
+ * one option.
246
+ *
247
+ * @since 3.0.0
248
+ *
249
+ * @param array $setting
250
+ */
251
+ public function render_static_setting( $setting ) {
252
+
253
+ ?>
254
+
255
+ <tr valign="top">
256
+ <th scope="row" class="titledesc">
257
+ <label for="<?php echo esc_attr( $setting['id'] ); ?>"><?php echo esc_html( $setting['title'] ); ?></label>
258
+ </th>
259
+ <td class="forminp forminp-<?php echo sanitize_title( $setting['type'] ) ?>">
260
+ <?php echo esc_html( $setting['label'] ); ?>
261
+ <input
262
+ name="<?php echo esc_attr( $setting['id'] ); ?>"
263
+ id="<?php echo esc_attr( $setting['id'] ); ?>"
264
+ value="<?php echo esc_html( $setting['value'] ); ?>"
265
+ type="hidden"
266
+ >
267
+ </td>
268
+ </tr><?php
269
+ }
270
+
271
+
272
+ /**
273
+ * Adds admin notices for configuration options that need attention.
274
+ *
275
+ * @since 3.0.0
276
+ */
277
+ public function add_admin_notices() {
278
+
279
+ // if the feature is not enabled, bail
280
+ if ( ! $this->handler->is_enabled() ) {
281
+ return;
282
+ }
283
+
284
+ // if not on the settings screen, bail
285
+ if ( ! $this->is_settings_screen() ) {
286
+ return;
287
+ }
288
+
289
+ $errors = array();
290
+
291
+ // HTTPS notice
292
+ if ( ! wc_site_is_https() ) {
293
+ $errors[] = __( 'Your site must be served over HTTPS with a valid SSL certificate.', 'woocommerce-square' );
294
+ }
295
+
296
+ // Currency notice
297
+ if ( ! in_array( get_woocommerce_currency(), $this->handler->get_accepted_currencies(), true ) ) {
298
+
299
+ $accepted_currencies = $this->handler->get_accepted_currencies();
300
+
301
+ $errors[] = sprintf(
302
+ /* translators: Placeholders: %1$s - plugin name, %2$s - a currency/comma-separated list of currencies, %3$s - <a> tag, %4$s - </a> tag */
303
+ _n(
304
+ 'Accepts payment in %1$s only. %2$sConfigure%3$s WooCommerce to accept %1$s to enable Apple Pay.',
305
+ 'Accepts payment in one of %1$s only. %2$sConfigure%3$s WooCommerce to accept one of %1$s to enable Apple Pay.',
306
+ count( $accepted_currencies ),
307
+ 'woocommerce-square'
308
+ ),
309
+ '<strong>' . implode( ', ', $accepted_currencies ) . '</strong>',
310
+ '<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=general' ) ) . '">',
311
+ '</a>'
312
+ );
313
+ }
314
+
315
+ // bad cert config notice
316
+ // this first checks if the option has been set so the notice is not
317
+ // displayed without the user having the chance to set it.
318
+ if ( false !== $this->handler->get_cert_path() && ! $this->handler->is_cert_configured() ) {
319
+
320
+ $errors[] = sprintf(
321
+ /** translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag */
322
+ __( 'Your %1$sMerchant Identity Certificate%2$s cannot be found. Please check your path configuration.', 'woocommerce-square' ),
323
+ '<strong>', '</strong>'
324
+ );
325
+ }
326
+
327
+ if ( ! empty( $errors ) ) {
328
+
329
+ $message = '<strong>' . __( 'Apple Pay is disabled.', 'woocommerce-square' ) . '</strong>';
330
+
331
+ if ( 1 === count( $errors ) ) {
332
+ $message .= ' ' . current( $errors );
333
+ } else {
334
+ $message .= '<ul><li>' . implode( '</li><li>', $errors ) . '</li></ul>';
335
+ }
336
+
337
+ $this->handler->get_plugin()->get_admin_notice_handler()->add_admin_notice( $message, 'apple-pay-https-required', array(
338
+ 'notice_class' => 'error',
339
+ 'dismissible' => false,
340
+ ) );
341
+ }
342
+ }
343
+
344
+
345
+ /**
346
+ * Determines if the user is currently on the settings screen.
347
+ *
348
+ * @since 3.0.0
349
+ *
350
+ * @return bool
351
+ */
352
+ protected function is_settings_screen() {
353
+
354
+ return 'wc-settings' === Square_Helper::get_request( 'page' ) && 'apple-pay' === Square_Helper::get_request( 'section' );
355
+ }
356
+
357
+
358
+ /**
359
+ * Gets the available display location options.
360
+ *
361
+ * @since 3.0.0
362
+ *
363
+ * @return array
364
+ */
365
+ protected function get_display_location_options() {
366
+
367
+ return array(
368
+ 'product' => __( 'Single products', 'woocommerce-square' ),
369
+ 'cart' => __( 'Cart', 'woocommerce-square' ),
370
+ 'checkout' => __( 'Checkout', 'woocommerce-square' ),
371
+ );
372
+ }
373
+
374
+
375
+ /**
376
+ * Gets the available gateway options.
377
+ *
378
+ * @since 3.0.0
379
+ *
380
+ * @return array
381
+ */
382
+ protected function get_gateway_options() {
383
+
384
+ $gateways = $this->handler->get_supporting_gateways();
385
+
386
+ foreach ( $gateways as $id => $gateway ) {
387
+ $gateways[ $id ] = $gateway->get_method_title();
388
+ }
389
+
390
+ return $gateways;
391
+ }
392
+ }
includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Ajax.php ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay AJAX class
4
+ *
5
+ * This file defines a class that registers AJAX callbacks
6
+ * for payments through Apply Pay.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay;
14
+
15
+ use WooCommerce\Square\Framework\Square_Helper;
16
+
17
+ defined( 'ABSPATH' ) or exit;
18
+
19
+ /**
20
+ * The Apple Pay AJAX handler.
21
+ *
22
+ * @since 3.0.0
23
+ */
24
+ class Payment_Gateway_Apple_Pay_AJAX {
25
+
26
+
27
+ /** @var Payment_Gateway_Apple_Pay $handler the Apple Pay handler instance */
28
+ protected $handler;
29
+
30
+
31
+ /**
32
+ * Constructs the class.
33
+ *
34
+ * @since 3.0.0
35
+ *
36
+ * @param Payment_Gateway_Apple_Pay $handler the Apple Pay handler instance
37
+ */
38
+ public function __construct( Payment_Gateway_Apple_Pay $handler ) {
39
+
40
+ $this->handler = $handler;
41
+
42
+ if ( $this->get_handler()->is_available() ) {
43
+
44
+ add_action( 'wp_ajax_sv_wc_apple_pay_get_payment_request', array( $this, 'get_payment_request' ) );
45
+ add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_get_payment_request', array( $this, 'get_payment_request' ) );
46
+
47
+ // validate the merchant
48
+ add_action( 'wp_ajax_sv_wc_apple_pay_validate_merchant', array( $this, 'validate_merchant' ) );
49
+ add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_validate_merchant', array( $this, 'validate_merchant' ) );
50
+
51
+ // recalculate the payment request totals
52
+ add_action( 'wp_ajax_sv_wc_apple_pay_recalculate_totals', array( $this, 'recalculate_totals' ) );
53
+ add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_recalculate_totals', array( $this, 'recalculate_totals' ) );
54
+
55
+ // process the payment
56
+ add_action( 'wp_ajax_sv_wc_apple_pay_process_payment', array( $this, 'process_payment' ) );
57
+ add_action( 'wp_ajax_nopriv_sv_wc_apple_pay_process_payment', array( $this, 'process_payment' ) );
58
+ }
59
+ }
60
+
61
+
62
+ /**
63
+ * Gets a payment request for the specified type.
64
+ *
65
+ * @internal
66
+ *
67
+ * @since 3.0.0
68
+ */
69
+ public function get_payment_request() {
70
+
71
+ $this->get_handler()->log( 'Getting payment request' );
72
+
73
+ try {
74
+
75
+ $request = $this->get_handler()->get_cart_payment_request( WC()->cart );
76
+
77
+ $this->get_handler()->log( sprintf( "Payment Request:\n %s", print_r( $request, true ) ) );
78
+
79
+ wp_send_json_success( wp_json_encode( $request ) );
80
+
81
+ } catch ( \Exception $e ) {
82
+
83
+ $this->get_handler()->log( sprintf( 'Could not build payment request. %s', $e->getMessage() ) );
84
+
85
+ wp_send_json_error( array(
86
+ 'message' => $e->getMessage(),
87
+ 'code' => $e->getCode(),
88
+ ) );
89
+ }
90
+ }
91
+
92
+
93
+ /**
94
+ * Validates the merchant.
95
+ *
96
+ * @internal
97
+ *
98
+ * @since 3.0.0
99
+ */
100
+ public function validate_merchant() {
101
+
102
+ $this->get_handler()->log( 'Validating merchant' );
103
+
104
+ check_ajax_referer( 'sv_wc_apple_pay_validate_merchant', 'nonce' );
105
+
106
+ $merchant_id = Square_Helper::get_post( 'merchant_id' );
107
+ $url = Square_Helper::get_post( 'url' );
108
+
109
+ try {
110
+
111
+ $response = $this->get_handler()->get_api()->validate_merchant( $url, $merchant_id, home_url(), get_bloginfo( 'name' ) );
112
+
113
+ wp_send_json_success( $response->get_merchant_session() );
114
+
115
+ } catch ( \Exception $e ) {
116
+
117
+ $this->get_handler()->log( sprintf( esc_html__( 'Could not validate merchant. %s', 'woocommerce-square' ), $e->getMessage() ) );
118
+
119
+ wp_send_json_error( array(
120
+ 'message' => $e->getMessage(),
121
+ 'code' => $e->getCode(),
122
+ ) );
123
+ }
124
+ }
125
+
126
+
127
+ /**
128
+ * Recalculates the totals for the current payment request.
129
+ *
130
+ * @internal
131
+ *
132
+ * @since 3.0.0
133
+ */
134
+ public function recalculate_totals() {
135
+
136
+ $this->get_handler()->log( 'Recalculating totals' );
137
+
138
+ check_ajax_referer( 'sv_wc_apple_pay_recalculate_totals', 'nonce' );
139
+
140
+ try {
141
+
142
+ // if a contact is passed, set the customer address data
143
+ if ( isset( $_REQUEST['contact'] ) && is_array( $_REQUEST['contact'] ) ) {
144
+
145
+ $contact = wp_parse_args( $_REQUEST['contact'], array(
146
+ 'administrativeArea' => null,
147
+ 'countryCode' => null,
148
+ 'locality' => null,
149
+ 'postalCode' => null,
150
+ ) );
151
+
152
+ $state = $contact['administrativeArea'];
153
+ $country = strtoupper( $contact['countryCode'] );
154
+ $city = $contact['locality'];
155
+ $postcode = $contact['postalCode'];
156
+
157
+ WC()->customer->set_shipping_city( $city );
158
+ WC()->customer->set_shipping_state( $state );
159
+ WC()->customer->set_shipping_country( $country );
160
+ WC()->customer->set_shipping_postcode( $postcode );
161
+
162
+ if ( $country ) {
163
+ WC()->customer->set_calculated_shipping( true );
164
+ }
165
+ }
166
+
167
+ $chosen_shipping_methods = ( $method = Square_Helper::get_request( 'method' ) ) ? array( wc_clean( $method ) ) : array();
168
+
169
+ WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
170
+
171
+ $payment_request = $this->get_handler()->recalculate_totals();
172
+
173
+ $data = array(
174
+ 'shipping_methods' => $payment_request['shippingMethods'],
175
+ 'line_items' => array_values( $payment_request['lineItems'] ),
176
+ 'total' => $payment_request['total'],
177
+ );
178
+
179
+ $this->get_handler()->log( sprintf( "New totals:\n %s", print_r( $data, true ) ) );
180
+
181
+ wp_send_json_success( $data );
182
+
183
+ } catch ( \Exception $e ) {
184
+
185
+ $this->get_handler()->log( $e->getMessage() );
186
+
187
+ wp_send_json_error( array(
188
+ 'message' => $e->getMessage(),
189
+ 'code' => $e->getCode(),
190
+ ) );
191
+ }
192
+ }
193
+
194
+
195
+ /**
196
+ * Processes the payment after the Apple Pay authorization.
197
+ *
198
+ * @internal
199
+ *
200
+ * @since 3.0.0
201
+ */
202
+ public function process_payment() {
203
+
204
+ $this->get_handler()->log( 'Processing payment' );
205
+
206
+ $type = Square_Helper::get_post( 'type' );
207
+ $response = stripslashes( Square_Helper::get_post( 'payment' ) );
208
+
209
+ $this->get_handler()->store_payment_response( $response );
210
+
211
+ try {
212
+
213
+ $result = $this->get_handler()->process_payment( $type, $response );
214
+
215
+ wp_send_json_success( $result );
216
+
217
+ } catch ( \Exception $e ) {
218
+
219
+ $this->get_handler()->log( sprintf( 'Payment failed. %s', $e->getMessage() ) );
220
+
221
+ wp_send_json_error( array(
222
+ 'message' => $e->getMessage(),
223
+ 'code' => $e->getCode(),
224
+ ) );
225
+ }
226
+ }
227
+
228
+
229
+ /**
230
+ * Gets the Apple Pay handler instance.
231
+ *
232
+ * @since 3.0.0
233
+ *
234
+ * @return Payment_Gateway_Apple_Pay
235
+ */
236
+ protected function get_handler() {
237
+
238
+ return $this->handler;
239
+ }
240
+ }
includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Frontend.php ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Frontend Class
4
+ *
5
+ * This file defines a class responsible to load features
6
+ * related to Apply Pay on the front end.
7
+ * Features such as loading assets, rendering Apply Pay button, etc.
8
+ *
9
+ * @package WooCommerce Square
10
+ * @subpackage Apple Pay
11
+ * @since 3.0.0
12
+ */
13
+
14
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay;
15
+ use WooCommerce\Square\Framework as SquareFramework;
16
+
17
+ defined( 'ABSPATH' ) or exit;
18
+
19
+ /**
20
+ * Sets up the Apple Pay front-end functionality.
21
+ *
22
+ * @since 3.0.0
23
+ */
24
+ class Payment_Gateway_Apple_Pay_Frontend {
25
+
26
+ /** @var SquareFramework\PaymentGateway\Payment_Gateway_Plugin $plugin the gateway plugin instance */
27
+ protected $plugin;
28
+
29
+ /** @var Payment_Gateway_Apple_Pay $handler the Apple Pay handler instance */
30
+ protected $handler;
31
+
32
+ /** @var SquareFramework\PaymentGateway\Payment_Gateway $gateway the gateway instance */
33
+ protected $gateway;
34
+
35
+
36
+ /**
37
+ * Constructs the class.
38
+ *
39
+ * @since 3.0.0
40
+ *
41
+ * @param SquareFramework\PaymentGateway\Payment_Gateway_Plugin $plugin the gateway plugin instance
42
+ * @param Payment_Gateway_Apple_Pay $handler the Apple Pay handler instance
43
+ */
44
+ public function __construct( SquareFramework\PaymentGateway\Payment_Gateway_Plugin $plugin, Payment_Gateway_Apple_Pay $handler ) {
45
+
46
+ $this->plugin = $plugin;
47
+
48
+ $this->handler = $handler;
49
+
50
+ $this->gateway = $this->get_handler()->get_processing_gateway();
51
+
52
+ if ( $this->get_handler()->is_available() ) {
53
+
54
+ add_action( 'wp', array( $this, 'init' ) );
55
+
56
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
57
+ }
58
+ }
59
+
60
+
61
+ /**
62
+ * Initializes the scripts and hooks.
63
+ *
64
+ * @since 3.0.0
65
+ */
66
+ public function init() {
67
+
68
+ $locations = $this->get_display_locations();
69
+
70
+ if ( is_product() && in_array( 'product', $locations, true ) ) {
71
+ $this->init_product();
72
+ } else if ( is_cart() && in_array( 'cart', $locations, true ) ) {
73
+ $this->init_cart();
74
+ } else if ( is_checkout() && in_array( 'checkout', $locations, true ) ) {
75
+ $this->init_checkout();
76
+ }
77
+ }
78
+
79
+
80
+ /**
81
+ * Gets the configured display locations.
82
+ *
83
+ * @since 3.0.0
84
+ *
85
+ * @return array
86
+ */
87
+ protected function get_display_locations() {
88
+
89
+ return get_option( 'sv_wc_apple_pay_display_locations', array() );
90
+ }
91
+
92
+
93
+ /**
94
+ * Enqueues the scripts.
95
+ *
96
+ * @since 3.0.0
97
+ */
98
+ public function enqueue_scripts() {
99
+
100
+ wp_enqueue_style( 'wc-square-apple-pay', $this->get_plugin()->get_plugin_url() . '/assets/css/frontend/wc-square-payment-gateway-apple-pay.css', array(), $this->get_plugin()->get_version() ); // TODO: min
101
+
102
+ wp_enqueue_script( 'wc-square-apple-pay', $this->get_plugin()->get_plugin_url() . '/assets/js/frontend/wc-square-payment-gateway-apple-pay.min.js', array( 'jquery' ), $this->get_plugin()->get_version(), true );
103
+
104
+ /**
105
+ * Filters the Apple Pay JS handler params.
106
+ *
107
+ * @since 3.0.0
108
+ * @param array $params the JS params
109
+ */
110
+ $params = apply_filters( 'sv_wc_apple_pay_js_handler_params', array(
111
+ 'gateway_id' => $this->get_gateway()->get_id(),
112
+ 'gateway_id_dasherized' => $this->get_gateway()->get_id_dasherized(),
113
+ 'merchant_id' => $this->get_handler()->get_merchant_id(),
114
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
115
+ 'validate_nonce' => wp_create_nonce( 'sv_wc_apple_pay_validate_merchant' ),
116
+ 'recalculate_totals_nonce' => wp_create_nonce( 'sv_wc_apple_pay_recalculate_totals' ),
117
+ 'process_nonce' => wp_create_nonce( 'sv_wc_apple_pay_process_payment' ),
118
+ 'generic_error' => __( 'An error occurred, please try again or try an alternate form of payment', 'woocommerce-square' ),
119
+ ) );
120
+
121
+ wp_localize_script( 'wc-square-apple-pay', 'sv_wc_apple_pay_params', $params );
122
+ }
123
+
124
+
125
+ /**
126
+ * Renders an Apple Pay button.
127
+ *
128
+ * @since 3.0.0
129
+ */
130
+ public function render_button() {
131
+
132
+ $button_text = '';
133
+ $classes = array(
134
+ 'sv-wc-apple-pay-button',
135
+ );
136
+
137
+ switch ( $this->get_handler()->get_button_style() ) {
138
+
139
+ case 'black':
140
+ $classes[] = 'apple-pay-button-black';
141
+ break;
142
+
143
+ case 'white':
144
+ $classes[] = 'apple-pay-button-white';
145
+ break;
146
+
147
+ case 'white-with-line':
148
+ $classes[] = 'apple-pay-button-white-with-line';
149
+ break;
150
+ }
151
+
152
+ // if on the single product page, add some text
153
+ if ( is_product() ) {
154
+ $classes[] = 'apple-pay-button-buy-now';
155
+ $button_text = __( 'Buy with', 'woocommerce-square' );
156
+ }
157
+
158
+ if ( $button_text ) {
159
+ $classes[] = 'apple-pay-button-with-text';
160
+ }
161
+
162
+ echo '<button class="' . implode( ' ', array_map( 'sanitize_html_class', $classes ) ) . '" lang="' . esc_attr( substr( get_locale(), 0, 2 ) ) . '">';
163
+
164
+ if ( $button_text ) {
165
+ echo '<span class="text">' . esc_html( $button_text ) . '</span><span class="logo"></span>';
166
+ }
167
+
168
+ echo '</button>';
169
+ }
170
+
171
+
172
+ /**
173
+ * Initializes Apple Pay on the single product page.
174
+ *
175
+ * @since 3.0.0
176
+ */
177
+ public function init_product() {
178
+
179
+ $args = array();
180
+
181
+ try {
182
+
183
+ $product = wc_get_product( get_the_ID() );
184
+
185
+ if ( ! $product ) {
186
+ throw new \Exception( __( 'Product does not exist.', 'woocommerce-square' ) );
187
+ }
188
+
189
+ $payment_request = $this->get_handler()->get_product_payment_request( $product );
190
+
191
+ $args['payment_request'] = $payment_request;
192
+
193
+ } catch ( \Exception $e ) {
194
+
195
+ $this->get_handler()->log( sprintf( 'Could not initialize Apple Pay. %s', $e->getMessage() ) );
196
+ }
197
+
198
+ /**
199
+ * Filters the Apple Pay product handler args.
200
+ *
201
+ * @since 3.0.0
202
+ * @param array $args
203
+ */
204
+ $args = apply_filters( 'sv_wc_apple_pay_product_handler_args', $args );
205
+
206
+ wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new Square_Apple_Pay_Product_Handler(%s);', wp_json_encode( $args ) ) );
207
+
208
+ add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'render_button' ) );
209
+ }
210
+
211
+
212
+ /** Cart functionality ****************************************************/
213
+
214
+
215
+ /**
216
+ * Initializes Apple Pay on the cart page.
217
+ *
218
+ * @since 3.0.0
219
+ */
220
+ public function init_cart() {
221
+
222
+ $args = array();
223
+
224
+ try {
225
+
226
+ $payment_request = $this->get_handler()->get_cart_payment_request( WC()->cart );
227
+
228
+ $args['payment_request'] = $payment_request;
229
+
230
+ } catch ( \Exception $e ) {
231
+
232
+ $args['payment_request'] = false;
233
+ }
234
+
235
+ /**
236
+ * Filters the Apple Pay cart handler args.
237
+ *
238
+ * @since 3.0.0
239
+ * @param array $args
240
+ */
241
+ $args = apply_filters( 'sv_wc_apple_pay_cart_handler_args', $args );
242
+
243
+ wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new Square_Apple_Pay_Cart_Handler(%s);', wp_json_encode( $args ) ) );
244
+
245
+ add_action( 'woocommerce_proceed_to_checkout', array( $this, 'render_button' ) );
246
+ }
247
+
248
+
249
+ /** Checkout functionality ************************************************/
250
+
251
+
252
+ /**
253
+ * Initializes Apple Pay on the checkout page.
254
+ *
255
+ * @since 3.0.0
256
+ */
257
+ public function init_checkout() {
258
+
259
+ /**
260
+ * Filters the Apple Pay checkout handler args.
261
+ *
262
+ * @since 3.0.0
263
+ * @param array $args
264
+ */
265
+ $args = apply_filters( 'sv_wc_apple_pay_checkout_handler_args', array() );
266
+
267
+ wc_enqueue_js( sprintf( 'window.sv_wc_apple_pay_handler = new Square_Apple_Pay_Checkout_Handler(%s);', wp_json_encode( $args ) ) );
268
+
269
+ if ( $this->get_plugin()->is_plugin_active( 'woocommerce-checkout-add-ons.php' ) ) {
270
+ add_action( 'woocommerce_review_order_before_payment', array( $this, 'render_button' ) );
271
+ } else {
272
+ add_action( 'woocommerce_before_checkout_form', array( $this, 'render_checkout_button' ), 15 );
273
+ }
274
+ }
275
+
276
+
277
+ /**
278
+ * Renders the Apple Pay button for checkout.
279
+ *
280
+ * @since 3.0.0
281
+ */
282
+ public function render_checkout_button() {
283
+
284
+ ?>
285
+
286
+ <div class="sv-wc-apply-pay-checkout">
287
+
288
+ <?php /** translators: Phrase that preceeds the Apple Pay logo, i.e. "Pay with [logo]" */
289
+ $button_text = __( 'Pay with', 'woocommerce-square' );
290
+
291
+ $this->render_button(); ?>
292
+
293
+ <span class="divider">
294
+ <?php /** translators: "or" as in "Pay with Apple Pay [or] regular checkout" */
295
+ esc_html_e( 'or', 'woocommerce-square' ); ?>
296
+ </span>
297
+
298
+ </div>
299
+
300
+ <?php
301
+ }
302
+
303
+
304
+ /**
305
+ * Gets the gateway instance.
306
+ *
307
+ * @since 3.0.0
308
+ *
309
+ * @return SquareFramework\PaymentGateway\Payment_Gateway
310
+ */
311
+ protected function get_gateway() {
312
+
313
+ return $this->gateway;
314
+ }
315
+
316
+
317
+ /**
318
+ * Gets the gateway plugin instance.
319
+ *
320
+ * @since 3.0.0
321
+ *
322
+ * @return SquareFramework\PaymentGateway\Payment_Gateway_Plugin
323
+ */
324
+ protected function get_plugin() {
325
+
326
+ return $this->plugin;
327
+ }
328
+
329
+ /**
330
+ * Gets the Apple Pay handler instance.
331
+ *
332
+ * @since 3.0.0
333
+ *
334
+ * @return Payment_Gateway_Apple_Pay
335
+ */
336
+ protected function get_handler() {
337
+
338
+ return $this->handler;
339
+ }
340
+ }
includes/Framework/PaymentGateway/ApplePay/Payment_Gateway_Apple_Pay_Orders.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Apple Pay Orders class
4
+ *
5
+ * This file defines a class that provides an API to modify orders
6
+ * created through Apple Pay.
7
+ *
8
+ * @package WooCommerce Square
9
+ * @subpackage Apple Pay
10
+ * @since 3.0.0
11
+ */
12
+
13
+ namespace WooCommerce\Square\Framework\PaymentGateway\ApplePay;
14
+
15
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
16
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
17
+
18
+ defined( 'ABSPATH' ) or exit;
19
+
20
+ /**
21
+ * The Apple Pay order handler.
22
+ *
23
+ * @since 3.0.0
24
+ */
25
+ class Payment_Gateway_Apple_Pay_Orders {
26
+
27
+ /**
28
+ * Creates an order from a cart.
29
+ *
30
+ * @since 3.0.0
31
+ *
32
+ * @param \WC_Cart $cart cart object
33
+ * @return \WC_Order|void
34
+ * @throws \Exception
35
+ * @throws \Exception
36
+ */
37
+ public static function create_order( \WC_Cart $cart ) {
38
+
39
+ if ( Plugin_Compatibility::is_wc_version_lt( '3.2' ) && ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
40
+ define( 'WOOCOMMERCE_CHECKOUT', true );
41
+ }
42
+
43
+ $cart->calculate_totals();
44
+
45
+ try {
46
+
47
+ wc_transaction_query( 'start' );
48
+
49
+ $order_data = array(
50
+ 'status' => apply_filters( 'woocommerce_default_order_status', 'pending' ),
51
+ 'customer_id' => get_current_user_id(),
52
+ 'cart_hash' => md5( wp_json_encode( wc_clean( $cart->get_cart_for_session() ) ) . $cart->total ),
53
+ 'created_via' => 'apple_pay',
54
+ );
55
+
56
+ $order = self::get_order_object( $order_data );
57
+
58
+ foreach ( $cart->get_cart() as $cart_item_key => $item ) {
59
+
60
+ $args = array(
61
+ 'variation' => $item['variation'],
62
+ 'totals' => array(
63
+ 'subtotal' => $item['line_subtotal'],
64
+ 'subtotal_tax' => $item['line_subtotal_tax'],
65
+ 'total' => $item['line_total'],
66
+ 'tax' => $item['line_tax'],
67
+ 'tax_data' => $item['line_tax_data']
68
+ ),
69
+ );
70
+
71
+ if ( ! $order->add_product( $item['data'], $item['quantity'], $args ) ) {
72
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 525 ) );
73
+ }
74
+ }
75
+
76
+ foreach ( $cart->get_coupons() as $code => $coupon ) {
77
+
78
+ if ( ! Order_Compatibility::add_coupon( $order, $code, $cart->get_coupon_discount_amount( $code ), $cart->get_coupon_discount_tax_amount( $code ) ) ) {
79
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 529 ) );
80
+ }
81
+ }
82
+
83
+ $chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() );
84
+
85
+ foreach ( WC()->shipping->get_packages() as $key => $package ) {
86
+
87
+ if ( isset( $package['rates'][ $chosen_methods[ $key ] ] ) ) {
88
+
89
+ $method = $package['rates'][ $chosen_methods[ $key ] ];
90
+
91
+ if ( ! Order_Compatibility::add_shipping( $order, $method ) ) {
92
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 527 ) );
93
+ }
94
+ }
95
+ }
96
+
97
+ // add fees
98
+ foreach ( $cart->get_fees() as $key => $fee ) {
99
+
100
+ if ( ! Order_Compatibility::add_fee( $order, $fee ) ) {
101
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 526 ) );
102
+ }
103
+ }
104
+
105
+ $cart_taxes = Plugin_Compatibility::is_wc_version_gte( '3.2' ) ? $cart->get_cart_contents_taxes() : $cart->taxes;
106
+ $shipping_taxes = Plugin_Compatibility::is_wc_version_gte( '3.2' ) ? $cart->get_shipping_taxes() : $cart->shipping_taxes;
107
+
108
+ foreach ( array_keys( $cart_taxes + $shipping_taxes ) as $rate_id ) {
109
+
110
+ if ( $rate_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $rate_id ) {
111
+
112
+ if ( ! Order_Compatibility::add_tax( $order, $rate_id, $cart->get_tax_amount( $rate_id ), $cart->get_shipping_tax_amount( $rate_id ) ) ) {
113
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 526 ) );
114
+ }
115
+ }
116
+ }
117
+
118
+ wc_transaction_query( 'commit' );
119
+
120
+ $order->update_taxes();
121
+
122
+ $order->calculate_totals( false ); // false to skip recalculating taxes
123
+
124
+ do_action( 'woocommerce_checkout_update_order_meta', Order_Compatibility::get_prop( $order, 'id' ), array() );
125
+
126
+ return $order;
127
+
128
+ } catch ( \Exception $e ) {
129
+
130
+ wc_transaction_query( 'rollback' );
131
+
132
+ throw $e;
133
+ }
134
+ }
135
+
136
+
137
+ /**
138
+ * Gets an order object for payment.
139
+ *
140
+ * @since 3.0.0
141
+ *
142
+ * @param array $order_data the order data
143
+ * @return \WC_Order
144
+ * @throws \Exception
145
+ */
146
+ public static function get_order_object( $order_data ) {
147
+
148
+ $order_id = (int) WC()->session->get( 'order_awaiting_payment', 0 );
149
+
150
+ if ( $order_id && $order_data['cart_hash'] === get_post_meta( $order_id, '_cart_hash', true ) && ( $order = wc_get_order( $order_id ) ) && $order->has_status( array( 'pending', 'failed' ) ) ) {
151
+
152
+ $order_data['order_id'] = $order_id;
153
+
154
+ $order = wc_update_order( $order_data );
155
+
156
+ if ( is_wp_error( $order ) ) {
157
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 522 ) );
158
+ } else {
159
+ $order->remove_order_items();
160
+ }
161
+
162
+ } else {
163
+
164
+ $order = wc_create_order( $order_data );
165
+
166
+ if ( is_wp_error( $order ) ) {
167
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 520 ) );
168
+ } elseif ( false === $order ) {
169
+ throw new \Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-square' ), 521 ) );
170
+ }
171
+
172
+ // set the new order ID so it can be resumed in case of failure
173
+ WC()->session->set( 'order_awaiting_payment', Order_Compatibility::get_prop( $order, 'id' ) );
174
+ }
175
+
176
+ return $order;
177
+ }
178
+ }
includes/Framework/PaymentGateway/Handlers/Capture.php ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Handlers;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
5
+ use WooCommerce\Square\Framework\Plugin_Compatibility;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Response;
8
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
9
+
10
+ defined( 'ABSPATH' ) or exit;
11
+
12
+ /**
13
+ * The transaction capture handler.
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Capture {
18
+
19
+
20
+ /** @var Payment_Gateway payment gateway instance */
21
+ private $gateway;
22
+
23
+
24
+ /**
25
+ * Capture constructor.
26
+ *
27
+ * @since 3.0.0
28
+ *
29
+ * @param Payment_Gateway $gateway payment gateway instance
30
+ */
31
+ public function __construct( Payment_Gateway $gateway ) {
32
+
33
+ $this->gateway = $gateway;
34
+
35
+ // auto-capture on order status change if enabled
36
+ if ( $gateway->supports_credit_card_capture() && $gateway->is_paid_capture_enabled() ) {
37
+ add_action( 'woocommerce_order_status_changed', array( $this, 'maybe_capture_paid_order' ), 10, 3 );
38
+ }
39
+ }
40
+
41
+
42
+ /**
43
+ * Captures an order on status change to a "paid" status.
44
+ *
45
+ * @internal
46
+ *
47
+ * @since 3.0.0
48
+ *
49
+ * @param int $order_id order ID
50
+ * @param string $old_status status being changed
51
+ * @param string $new_status new order status
52
+ */
53
+ public function maybe_capture_paid_order( $order_id, $old_status, $new_status ) {
54
+
55
+ $paid_statuses = wc_get_is_paid_statuses();
56
+
57
+ // bail if changing to a non-paid status or from a paid status
58
+ if ( ! in_array( $new_status, $paid_statuses, true ) || in_array( $old_status, $paid_statuses, true ) ) {
59
+ return;
60
+ }
61
+
62
+ $order = wc_get_order( $order_id );
63
+
64
+ if ( ! $order ) {
65
+ return;
66
+ }
67
+
68
+ $payment_method = Order_Compatibility::get_prop( $order, 'payment_method' );
69
+
70
+ if ( $payment_method !== $this->get_gateway()->get_id() ) {
71
+ return;
72
+ }
73
+
74
+ $this->maybe_perform_capture( $order );
75
+ }
76
+
77
+
78
+ /**
79
+ * Perform a capture on an order if it can be captured.
80
+ *
81
+ * This acts as a wrapper for when the process should just bail without logging any errors or order notes, like when
82
+ * performing capture via bulk action.
83
+ *
84
+ * @since 3.0.0
85
+ *
86
+ * @param \WC_Order $order order object
87
+ * @param float|null $amount amount to capture
88
+ * @return bool
89
+ */
90
+ public function maybe_perform_capture( \WC_Order $order, $amount = null ) {
91
+
92
+ // don't log any errors for for orders that can't be captured
93
+ if ( ! $this->order_can_be_captured( $order ) ) {
94
+ return false;
95
+ }
96
+
97
+ $result = $this->perform_capture( $order, $amount );
98
+
99
+ return ! empty( $result['success'] );
100
+ }
101
+
102
+
103
+ /**
104
+ * Performs a credit card capture for an order.
105
+ *
106
+ * @since 3.0.0
107
+ *
108
+ * @param \WC_Order $order WooCommerce order object
109
+ * @param float|null $amount amount to capture
110
+ * @return array {
111
+ * Capture transaction results
112
+ *
113
+ * @type bool $success whether the capture was successful
114
+ * @type int $code result code
115
+ * @type string $message result message
116
+ * }
117
+ */
118
+ public function perform_capture( \WC_Order $order, $amount = null ) {
119
+
120
+ $order = $this->get_gateway()->get_order_for_capture( $order, $amount );
121
+
122
+ try {
123
+
124
+ // notify if the gateway doesn't support captures when this is called directly
125
+ if ( ! $this->get_gateway()->supports_credit_card_capture() ) {
126
+
127
+ $message = "{$this->get_gateway()->get_method_title()} does not support payment captures";
128
+
129
+ Plugin_Compatibility::wc_doing_it_wrong( __METHOD__, $message, '3.0.0' );
130
+
131
+ throw new \Exception( $message, 500 );
132
+ }
133
+
134
+ // don't try to capture failed/cancelled/fully refunded transactions
135
+ if ( ! $this->is_order_ready_for_capture( $order ) ) {
136
+ throw new \Exception( __( 'Order cannot be captured', 'woocommerce-square' ), 400 );
137
+ }
138
+
139
+ // don't re-capture fully captured orders
140
+ if ( $this->has_order_authorization_expired( $order ) ) {
141
+ throw new \Exception( __( 'Transaction authorization has expired', 'woocommerce-square' ), 400 );
142
+ }
143
+
144
+ // don't re-capture fully captured orders
145
+ if ( $this->is_order_fully_captured( $order ) ) {
146
+ throw new \Exception( __( 'Transaction has already been fully captured', 'woocommerce-square' ), 400 );
147
+ }
148
+
149
+ // generally unavailable
150
+ if ( ! $this->order_can_be_captured( $order ) ) {
151
+ throw new \Exception( __( 'Transaction cannot be captured', 'woocommerce-square' ), 400 );
152
+ }
153
+
154
+ // attempt the capture
155
+ $response = $this->get_gateway()->get_api()->credit_card_capture( $order );
156
+
157
+ // bail early if the capture wasn't approved
158
+ if ( ! $response->transaction_approved() ) {
159
+
160
+ $this->do_capture_failed( $order, $response );
161
+
162
+ throw new \Exception( $response->get_status_code() . ' - ' . $response->get_status_message() );
163
+ }
164
+
165
+ $message = sprintf(
166
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - transaction amount. Definitions: Capture, as in capture funds from a credit card. */
167
+ esc_html__( '%1$s Capture of %2$s Approved', 'woocommerce-square' ),
168
+ $this->get_gateway()->get_method_title(),
169
+ wc_price( $order->capture->amount, array( 'currency' => Order_Compatibility::get_prop( $order, 'currency', 'view' ) ) )
170
+ );
171
+
172
+ // adds the transaction id (if any) to the order note
173
+ if ( $response->get_transaction_id() ) {
174
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
175
+ }
176
+
177
+ $order->add_order_note( $message );
178
+
179
+ // add the standard capture data to the order
180
+ $this->do_capture_success( $order, $response );
181
+
182
+ // if the original auth amount has been captured, complete payment
183
+ if ( $this->get_gateway()->get_order_meta( $order, 'capture_total' ) >= $order->get_total() ) {
184
+
185
+ // prevent stock from being reduced when payment is completed as this is done when the charge was authorized
186
+ add_filter( 'woocommerce_payment_complete_reduce_order_stock', '__return_false', 100 );
187
+
188
+ // complete the order
189
+ $order->payment_complete();
190
+ }
191
+
192
+ return array(
193
+ 'success' => true,
194
+ 'code' => 200,
195
+ 'message' => $message,
196
+ );
197
+
198
+ } catch ( \Exception $exception ) {
199
+
200
+ // add an order note if this isn't a general error
201
+ if ( 500 !== $exception->getCode() ) {
202
+
203
+ $note_message = sprintf(
204
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - failure message. Definitions: "capture" as in capturing funds from a credit card. */
205
+ esc_html__( '%1$s Capture Failed: %2$s', 'woocommerce-square' ),
206
+ $this->get_gateway()->get_method_title(),
207
+ $exception->getMessage()
208
+ );
209
+
210
+ $order->add_order_note( $note_message );
211
+ }
212
+
213
+ return array(
214
+ 'success' => false,
215
+ 'code' => $exception->getCode(),
216
+ 'message' => $exception->getMessage(),
217
+ );
218
+ }
219
+ }
220
+
221
+
222
+ /**
223
+ * Adds the standard capture data to an order.
224
+ *
225
+ * @since 3.0.0
226
+ *
227
+ * @param \WC_Order $order the order object
228
+ * @param Payment_Gateway_API_Response $response transaction response
229
+ */
230
+ public function do_capture_success( \WC_Order $order, Payment_Gateway_API_Response $response ) {
231
+
232
+ $total_captured = (float) $this->get_gateway()->get_order_meta( $order, 'capture_total' ) + (float) $order->capture->amount;
233
+
234
+ $this->get_gateway()->update_order_meta( $order, 'capture_total', Square_Helper::number_format( $total_captured ) );
235
+ $this->get_gateway()->update_order_meta( $order, 'charge_captured', $this->get_gateway()->supports_credit_card_partial_capture() && $this->get_gateway()->is_partial_capture_enabled() && $total_captured < (float) $this->get_order_capture_maximum( $order ) ? 'partial' : 'yes' );
236
+
237
+ // add capture transaction ID
238
+ if ( $response && $response->get_transaction_id() ) {
239
+ $this->get_gateway()->update_order_meta( $order, 'capture_trans_id', $response->get_transaction_id() );
240
+ }
241
+ }
242
+
243
+
244
+ /**
245
+ * Lets gateways handle any specific capture failure results for the order.
246
+ *
247
+ * @since 3.0.0
248
+ *
249
+ * @param \WC_Order $order WooCommerce order object
250
+ * @param Payment_Gateway_API_Response $response API response object
251
+ */
252
+ public function do_capture_failed( \WC_Order $order, Payment_Gateway_API_Response $response ) { }
253
+
254
+
255
+ /** Conditional Methods *******************************************************************************************/
256
+
257
+
258
+ /**
259
+ * Determines if an order is eligible for capture.
260
+ *
261
+ * @since 3.0.0
262
+ *
263
+ * @param \WC_Order $order order object
264
+ * @return bool
265
+ */
266
+ public function order_can_be_captured( \WC_Order $order ) {
267
+
268
+ // check whether the charge has already been captured by this gateway
269
+ if ( ! $this->is_order_ready_for_capture( $order ) || $this->is_order_fully_captured( $order ) ) {
270
+ return false;
271
+ }
272
+
273
+ // if for any reason the authorization can not be captured
274
+ if ( 'no' === $this->get_gateway()->get_order_meta( $order, 'auth_can_be_captured' ) ) {
275
+ return false;
276
+ }
277
+
278
+ // authorization hasn't already been captured, but has it expired?
279
+ return ! $this->has_order_authorization_expired( $order );
280
+ }
281
+
282
+
283
+ /**
284
+ * Determines if an order is ready for capture.
285
+ *
286
+ * The base implementation of this method checks for a valid order status and that a transaction ID is set.
287
+ *
288
+ * @since 3.0.0
289
+ *
290
+ * @param \WC_Order $order order object
291
+ * @return bool
292
+ */
293
+ public function is_order_ready_for_capture( \WC_Order $order ) {
294
+
295
+ return ! in_array( $order->get_status(), array( 'cancelled', 'refunded', 'failed' ), true ) && $this->get_gateway()->get_order_meta( $order, 'trans_id' );
296
+ }
297
+
298
+
299
+ /**
300
+ * Determines if an order has been fully captured
301
+ *
302
+ * @since 3.0.0
303
+ *
304
+ * @param \WC_Order $order
305
+ * @return bool
306
+ */
307
+ public function is_order_fully_captured( \WC_Order $order ) {
308
+
309
+ $captured = 'yes' === $this->get_gateway()->get_order_meta( $order, 'charge_captured' );
310
+
311
+ if ( ! $captured && $this->get_gateway()->supports_credit_card_partial_capture() && $this->get_gateway()->is_partial_capture_enabled() ) {
312
+ $captured = (float) $this->get_gateway()->get_order_meta( $order, 'capture_total' ) >= (float) $this->get_order_capture_maximum( $order );
313
+ }
314
+
315
+ return $captured;
316
+ }
317
+
318
+
319
+ /**
320
+ * Determines if an order's authorization has expired.
321
+ *
322
+ * @since 3.0.0
323
+ *
324
+ * @param \WC_Order $order
325
+ * @return bool
326
+ */
327
+ public function has_order_authorization_expired( \WC_Order $order ) {
328
+
329
+ $transaction_date = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'trans_date' );
330
+
331
+ $transaction_time = strtotime( $transaction_date );
332
+
333
+ return $transaction_date && floor( ( time() - $transaction_time ) / 3600 ) > $this->get_gateway()->get_authorization_time_window();
334
+ }
335
+
336
+
337
+ /**
338
+ * Determines if an order's authorization has been captured, even partially.
339
+ *
340
+ * @since 3.0.0
341
+ *
342
+ * @param \WC_Order $order order object
343
+ * @return bool
344
+ */
345
+ public function is_order_captured( \WC_Order $order ) {
346
+
347
+ return in_array( $this->get_gateway()->get_order_meta( $order, 'charge_captured' ), array( 'yes', 'partial' ), true );
348
+ }
349
+
350
+
351
+ /** Getter Methods ************************************************************************************************/
352
+
353
+
354
+ /**
355
+ * Gets the maximum amount that can be captured from an order.
356
+ *
357
+ * Gateways can override this for an value above or below the order total.
358
+ * For instance, some processors allow capturing an amount a certain
359
+ * percentage higher than the payment total.
360
+ *
361
+ * @since 3.0.0
362
+ *
363
+ * @param \WC_Order $order WooCommerce order object
364
+ * @return float
365
+ */
366
+ public function get_order_capture_maximum( \WC_Order $order ) {
367
+
368
+ return $this->get_order_authorization_amount( $order );
369
+ }
370
+
371
+
372
+ /**
373
+ * Gets the amount originally authorized for an order.
374
+ *
375
+ * @since 3.0.0
376
+ *
377
+ * @param \WC_Order $order order object
378
+ * @return float
379
+ */
380
+ public function get_order_authorization_amount( \WC_Order $order ) {
381
+
382
+ // if a specific auth amount was stored, use it
383
+ // otherwise, use the order total
384
+ $amount = $this->get_gateway()->get_order_meta( $order, 'authorization_amount' ) ?: $order->get_total();
385
+
386
+ return (float) $amount;
387
+ }
388
+
389
+
390
+ /**
391
+ * Gets the payment gateway instance.
392
+ *
393
+ * @since 3.0.0
394
+ *
395
+ * @return Payment_Gateway
396
+ */
397
+ protected function get_gateway() {
398
+ return $this->gateway;
399
+ }
400
+ }
includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Integrations;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * Abstract Integration
10
+ *
11
+ * @since 3.0.0
12
+ */
13
+ abstract class Payment_Gateway_Integration {
14
+
15
+
16
+ /** @var Payment_Gateway direct gateway instance */
17
+ protected $gateway;
18
+
19
+
20
+ /**
21
+ * Bootstraps the class.
22
+ *
23
+ * @since 3.0.0
24
+ *
25
+ * @param Payment_Gateway $gateway direct gateway instance
26
+ */
27
+ public function __construct( Payment_Gateway $gateway ) {
28
+
29
+ $this->gateway = $gateway;
30
+ }
31
+
32
+
33
+ /**
34
+ * Return the gateway for the integration
35
+ *
36
+ * @since 3.0.0
37
+ * @return Payment_Gateway
38
+ */
39
+ public function get_gateway() {
40
+
41
+ return $this->gateway;
42
+ }
43
+ }
includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Pre_Orders.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Integrations;
4
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
5
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
6
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
7
+ use WooCommerce\Square\Framework\Square_Helper;
8
+
9
+ defined( 'ABSPATH' ) or exit;
10
+
11
+ /**
12
+ * Pre-Orders Integration
13
+ *
14
+ * @since 3.0.0
15
+ */
16
+ class Payment_Gateway_Integration_Pre_Orders extends Payment_Gateway_Integration {
17
+
18
+
19
+ /**
20
+ * Bootstrap class
21
+ *
22
+ * @since 3.0.0
23
+ *
24
+ * @param Payment_Gateway|Payment_Gateway_Direct $gateway gateway object
25
+ */
26
+ public function __construct( Payment_Gateway $gateway ) {
27
+
28
+ parent::__construct( $gateway );
29
+
30
+ // add hooks
31
+ $this->add_support();
32
+ }
33
+
34
+
35
+ /**
36
+ * Adds support for pre-orders by hooking in some necessary actions
37
+ *
38
+ * @since 3.0.0
39
+ */
40
+ public function add_support() {
41
+
42
+ $this->get_gateway()->add_support( array( 'pre-orders' ) );
43
+
44
+ // force tokenization when needed
45
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokenization_forced', array( $this, 'maybe_force_tokenization' ) );
46
+
47
+ // add pre-orders data to the order object
48
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_get_order', array( $this, 'get_order' ) );
49
+
50
+ // process pre-order initial payment as needed
51
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_process_payment', array( $this, 'process_payment' ), 10, 2 );
52
+
53
+ // complete a successful pre-order initial payment
54
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_complete_payment', array( $this, 'complete_payment' ), 10, 2 );
55
+
56
+ // process batch pre-order payments
57
+ add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->get_gateway()->get_id(), array( $this, 'process_release_payment' ) );
58
+ }
59
+
60
+
61
+ /**
62
+ * Force tokenization for pre-orders
63
+ *
64
+ * @since 3.0.0
65
+ * @see Payment_Gateway::tokenization_forced()
66
+ * @param boolean $force_tokenization whether tokenization should be forced
67
+ * @return boolean true if tokenization should be forced, false otherwise
68
+ */
69
+ public function maybe_force_tokenization( $force_tokenization ) {
70
+
71
+ // pay page with pre-order?
72
+ $pay_page_pre_order = false;
73
+ if ( $this->get_gateway()->is_pay_page_gateway() ) {
74
+
75
+ $order_id = $this->get_gateway()->get_checkout_pay_page_order_id();
76
+
77
+ if ( $order_id ) {
78
+ $pay_page_pre_order = \WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) && \WC_Pre_Orders_Product::product_is_charged_upon_release( \WC_Pre_Orders_Order::get_pre_order_product( $order_id ) );
79
+ }
80
+ }
81
+
82
+ if ( ( \WC_Pre_Orders_Cart::cart_contains_pre_order() && \WC_Pre_Orders_Product::product_is_charged_upon_release( \WC_Pre_Orders_Cart::get_pre_order_product() ) ) ||
83
+ $pay_page_pre_order ) {
84
+
85
+ // always tokenize the card for pre-orders that are charged upon release
86
+ $force_tokenization = true;
87
+ }
88
+
89
+ return $force_tokenization;
90
+ }
91
+
92
+
93
+ /**
94
+ * Adds pre-orders data to the order object.
95
+ *
96
+ * Filtered onto Payment_Gateway::get_order()
97
+ *
98
+ * @see Payment_Gateway::get_order()
99
+ *
100
+ * @since 3.0.0
101
+ *
102
+ * @param \WC_Order $order the order
103
+ * @return \WC_Order
104
+ */
105
+ public function get_order( $order ) {
106
+
107
+ // bail if order doesn't contain a pre-order
108
+ if ( ! \WC_Pre_Orders_Order::order_contains_pre_order( $order ) ) {
109
+ return $order;
110
+ }
111
+
112
+ if ( \WC_Pre_Orders_Order::order_requires_payment_tokenization( $order ) ) {
113
+
114
+ // normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be
115
+ if ( 0 == $order->get_user_id() && false !== ( $customer_id = $this->get_gateway()->get_guest_customer_id( $order ) ) ) {
116
+ $order->customer_id = $customer_id;
117
+ }
118
+
119
+ // zero out the payment total since we're just tokenizing the payment method
120
+ $order->payment_total = '0.00';
121
+
122
+ } elseif ( \WC_Pre_Orders_Order::order_has_payment_token( $order ) && ! is_checkout_pay_page() ) {
123
+
124
+ // if this is a pre-order release payment with a tokenized payment method, get the payment token to complete the order
125
+
126
+ // retrieve the payment token
127
+ $order->payment->token = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'payment_token' );
128
+
129
+ // retrieve the optional customer id
130
+ $order->customer_id = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'customer_id' );
131
+
132
+ // set token data on order
133
+ if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $order->payment->token ) ) {
134
+
135
+ // an existing registered user with a saved payment token
136
+ $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token );
137
+
138
+ // account last four
139
+ $order->payment->account_number = $token->get_last_four();
140
+
141
+ if ( $this->get_gateway()->is_credit_card_gateway() ) {
142
+
143
+ // card type
144
+ $order->payment->card_type = $token->get_card_type();
145
+
146
+ // exp month/year
147
+ $order->payment->exp_month = $token->get_exp_month();
148
+ $order->payment->exp_year = $token->get_exp_year();
149
+
150
+ }
151
+
152
+ } else {
153
+
154
+ // a guest user means that token data must be set from the original order
155
+
156
+ // account number
157
+ $order->payment->account_number = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'account_four' );
158
+
159
+ if ( $this->get_gateway()->is_credit_card_gateway() ) {
160
+
161
+ // card type
162
+ $order->payment->card_type = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'card_type' );
163
+
164
+ // expiry date
165
+ if ( $expiry_date = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'card_expiry_date' ) ) {
166
+ list( $exp_year, $exp_month ) = explode( '-', $expiry_date );
167
+ $order->payment->exp_month = $exp_month;
168
+ $order->payment->exp_year = $exp_year;
169
+ }
170
+
171
+ }
172
+ }
173
+ }
174
+
175
+ return $order;
176
+ }
177
+
178
+
179
+ /**
180
+ * Handle the pre-order initial payment/tokenization, or defer back to the normal payment
181
+ * processing flow
182
+ *
183
+ * @since 3.0.0
184
+ * @see Payment_Gateway::process_payment()
185
+ * @param boolean $result the result of this pre-order payment process
186
+ * @param int $order_id the order identifier
187
+ * @return true|array true to process this payment as a regular transaction, otherwise
188
+ * return an array containing keys 'result' and 'redirect'
189
+ */
190
+ public function process_payment( $result, $order_id ) {
191
+
192
+ // processing pre-order
193
+ if ( \WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) &&
194
+ \WC_Pre_Orders_Order::order_requires_payment_tokenization( $order_id ) ) {
195
+
196
+ $order = $this->get_gateway()->get_order( $order_id );
197
+
198
+ try {
199
+
200
+ // using an existing tokenized payment method
201
+ if ( isset( $order->payment->token ) && $order->payment->token ) {
202
+
203
+ // save the tokenized card info for completing the pre-order in the future
204
+ $this->get_gateway()->add_transaction_data( $order );
205
+
206
+ } else {
207
+
208
+ // otherwise tokenize the payment method
209
+ $order = $this->get_gateway()->get_payment_tokens_handler()->create_token( $order );
210
+ }
211
+
212
+ // mark order as pre-ordered / reduce order stock
213
+ \WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
214
+
215
+ // empty cart
216
+ WC()->cart->empty_cart();
217
+
218
+ // redirect to thank you page
219
+ $result = array(
220
+ 'result' => 'success',
221
+ 'redirect' => $this->get_gateway()->get_return_url( $order ),
222
+ );
223
+
224
+ } catch( \Exception $e ) {
225
+
226
+ $this->get_gateway()->mark_order_as_failed( $order, sprintf( esc_html__( 'Pre-Order Tokenization attempt failed (%s)', 'woocommerce-square' ), $this->get_gateway()->get_method_title(), $e->getMessage() ) );
227
+
228
+ $result = array(
229
+ 'result' => 'failure',
230
+ 'message' => $e->getMessage(),
231
+ );
232
+ }
233
+ }
234
+
235
+ return $result;
236
+ }
237
+
238
+
239
+ /**
240
+ * Completes a pre-order payment by marking the order as Pre-Ordered.
241
+ *
242
+ * @internal
243
+ *
244
+ * @since 3.0.0
245
+ *
246
+ * @param \WC_Order $order order object
247
+ */
248
+ public function complete_payment( $order ) {
249
+
250
+ if ( \WC_Pre_Orders_Order::order_contains_pre_order( $order ) && \WC_Pre_Orders_Order::order_requires_payment_tokenization( $order ) ) {
251
+ \WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
252
+ }
253
+ }
254
+
255
+
256
+ /**
257
+ * Processes a pre-order payment when the pre-order is released.
258
+ *
259
+ * @since 3.0.0
260
+ *
261
+ * @param \WC_Order $order original order containing the pre-order
262
+ * @throws \Exception
263
+ */
264
+ public function process_release_payment( $order ) {
265
+
266
+ try {
267
+
268
+ // set order defaults
269
+ $order = $this->get_gateway()->get_order( Order_Compatibility::get_prop( $order, 'id' ) );
270
+
271
+ // order description
272
+ $order->description = sprintf( esc_html__( '%s - Pre-Order Release Payment for Order %s', 'woocommerce-square' ), Square_Helper::get_site_name(), $order->get_order_number() );
273
+
274
+ // token is required
275
+ if ( ! $order->payment->token ) {
276
+ throw new \Exception( esc_html__( 'Payment token missing/invalid.', 'woocommerce-square' ) );
277
+ }
278
+
279
+ // perform the transaction
280
+ if ( $this->get_gateway()->is_credit_card_gateway() ) {
281
+
282
+ if ( $this->get_gateway()->perform_credit_card_charge( $order ) ) {
283
+ $response = $this->get_gateway()->get_api()->credit_card_charge( $order );
284
+ } else {
285
+ $response = $this->get_gateway()->get_api()->credit_card_authorization( $order );
286
+ }
287
+
288
+ }
289
+
290
+ // success! update order record
291
+ if ( $response->transaction_approved() ) {
292
+
293
+ $last_four = substr( $order->payment->account_number, -4 );
294
+
295
+ // order note based on gateway type
296
+ if ( $this->get_gateway()->is_credit_card_gateway() ) {
297
+
298
+ $message = sprintf(
299
+ esc_html__( '%s %s Pre-Order Release Payment Approved: %s ending in %s (expires %s)', 'woocommerce-square' ),
300
+ $this->get_gateway()->get_method_title(),
301
+ $this->get_gateway()->perform_credit_card_authorization( $order ) ? 'Authorization' : 'Charge',
302
+ Payment_Gateway_Helper::payment_type_to_name( ( ! empty( $order->payment->card_type ) ? $order->payment->card_type : 'card' ) ),
303
+ $last_four,
304
+ ( ! empty( $order->payment->exp_month) && ! empty( $order->payment->exp_year ) ? $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) : 'n/a' )
305
+ );
306
+
307
+ }
308
+
309
+ // adds the transaction id (if any) to the order note
310
+ if ( $response->get_transaction_id() ) {
311
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
312
+ }
313
+
314
+ $order->add_order_note( $message );
315
+ }
316
+
317
+ if ( $response->transaction_approved() || $response->transaction_held() ) {
318
+
319
+ // add the standard transaction data
320
+ $this->get_gateway()->add_transaction_data( $order, $response );
321
+
322
+ // allow the concrete class to add any gateway-specific transaction data to the order
323
+ $this->get_gateway()->add_payment_gateway_transaction_data( $order, $response );
324
+
325
+ // if the transaction was held (ie fraud validation failure) mark it as such
326
+ if ( $response->transaction_held() || ( $this->get_gateway()->supports( Payment_Gateway::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->get_gateway()->perform_credit_card_authorization( $order ) ) ) {
327
+
328
+ $this->get_gateway()->mark_order_as_held( $order, $this->get_gateway()->supports( Payment_Gateway::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->get_gateway()->perform_credit_card_authorization( $order ) ? esc_html__( 'Authorization only transaction', 'woocommerce-square' ) : $response->get_status_message(), $response );
329
+
330
+ wc_reduce_stock_levels( $order->get_id() ); // reduce stock for held orders, but don't complete payment
331
+
332
+ } else {
333
+ // otherwise complete the order
334
+ $order->payment_complete();
335
+ }
336
+
337
+ } else {
338
+
339
+ // failure
340
+ throw new \Exception( sprintf( '%s: %s', $response->get_status_code(), $response->get_status_message() ) );
341
+
342
+ }
343
+
344
+ } catch ( \Exception $e ) {
345
+
346
+ // Mark order as failed
347
+ $this->get_gateway()->mark_order_as_failed( $order, sprintf( esc_html__( 'Pre-Order Release Payment Failed: %s', 'woocommerce-square' ), $e->getMessage() ) );
348
+
349
+ }
350
+ }
351
+ }
includes/Framework/PaymentGateway/Integrations/Payment_Gateway_Integration_Subscriptions.php ADDED
@@ -0,0 +1,673 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\Integrations;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
5
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Token;
8
+
9
+ defined( 'ABSPATH' ) or exit;
10
+
11
+ /**
12
+ * Subscriptions Integration
13
+ *
14
+ * @since 3.0.0
15
+ */
16
+ class Payment_Gateway_Integration_Subscriptions extends Payment_Gateway_Integration {
17
+
18
+
19
+ /** @var string|float renewal payment total for Subs 2.0.x renewals */
20
+ protected $renewal_payment_total;
21
+
22
+
23
+ /**
24
+ * Bootstraps the class.
25
+ *
26
+ * @since 3.0.0
27
+ *
28
+ * @param Payment_Gateway|Payment_Gateway_Direct $gateway
29
+ */
30
+ public function __construct( Payment_Gateway $gateway ) {
31
+
32
+ parent::__construct( $gateway );
33
+
34
+ // add hooks
35
+ $this->add_support();
36
+ }
37
+
38
+
39
+ /**
40
+ * Adds support for subscriptions by hooking in some necessary actions
41
+ *
42
+ * @since 3.0.0
43
+ */
44
+ public function add_support() {
45
+
46
+ $this->get_gateway()->add_support( array(
47
+ 'subscriptions',
48
+ 'subscription_suspension',
49
+ 'subscription_cancellation',
50
+ 'subscription_reactivation',
51
+ 'subscription_amount_changes',
52
+ 'subscription_date_changes',
53
+ 'multiple_subscriptions',
54
+ 'subscription_payment_method_change_customer',
55
+ 'subscription_payment_method_change_admin',
56
+ ) );
57
+
58
+ // force tokenization when needed
59
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokenization_forced', array( $this, 'maybe_force_tokenization' ) );
60
+
61
+ // save token/customer ID to subscription objects
62
+ add_action( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_add_transaction_data', array( $this, 'save_payment_meta' ), 10, 2 );
63
+
64
+ // process renewal payments
65
+ add_action( 'woocommerce_scheduled_subscription_payment_' . $this->get_gateway()->get_id(), array( $this, 'process_renewal_payment' ), 10, 2 );
66
+
67
+ // update the customer/token ID on the subscription when updating a previously failing payment method
68
+ add_action( 'woocommerce_subscription_failing_payment_method_updated_' . $this->get_gateway()->get_id(), array( $this, 'update_failing_payment_method' ), 10, 2 );
69
+
70
+ // display the current payment method used for a subscription in the "My Subscriptions" table
71
+ add_filter( 'woocommerce_my_subscriptions_payment_method', array( $this, 'maybe_render_payment_method' ), 10, 3 );
72
+
73
+ // don't copy over order-specific meta to the WC_Subscription object during renewal processing
74
+ add_filter( 'wcs_renewal_order_meta', array( $this, 'do_not_copy_order_meta' ) );
75
+
76
+ // process the Change Payment "transaction"
77
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_process_payment', array( $this, 'process_change_payment' ), 10, 3 );
78
+
79
+ // remove order-specific meta from the Subscription object after the change payment method action
80
+ add_filter( 'woocommerce_subscriptions_process_payment_for_change_method_via_pay_shortcode', array( $this, 'remove_order_meta_from_change_payment' ), 10, 2 );
81
+
82
+ // don't copy over order-specific meta to the new WC_Subscription object during upgrade to 2.0.x
83
+ add_filter( 'wcs_upgrade_subscription_meta_to_copy', array( $this, 'do_not_copy_order_meta_during_upgrade' ) );
84
+
85
+ // allow concrete gateways to define additional order-specific meta keys to exclude
86
+ if ( is_callable( array( $this->get_gateway(), 'subscriptions_get_excluded_order_meta_keys' ) ) ) {
87
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_subscriptions_order_specific_meta_keys', array( $this->get_gateway(), 'subscriptions_get_excluded_order_meta_keys' ) );
88
+ }
89
+
90
+ /* My Payment Methods */
91
+
92
+ add_filter( 'wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_headers', array( $this, 'add_my_payment_methods_table_header' ), 10, 2 );
93
+ add_filter( 'wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_body_row_data', array( $this, 'add_my_payment_methods_table_body_row_data' ), 10, 3 );
94
+ add_filter( 'wc_' . $this->get_gateway()->get_plugin()->get_id() . '_my_payment_methods_table_method_actions', array( $this, 'disable_my_payment_methods_table_method_delete' ), 10, 3 );
95
+
96
+ /* Admin Change Payment Method support */
97
+
98
+ // framework defaults - payment_token and customer_id
99
+ add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'admin_add_payment_meta' ), 9, 2 );
100
+ add_action( 'woocommerce_subscription_validate_payment_meta_' . $this->get_gateway()->get_id(), array( $this, 'admin_validate_payment_meta' ), 9 );
101
+
102
+ // allow concrete gateways to add/change defaults
103
+ if ( is_callable( array( $this->get_gateway(), 'subscriptions_admin_add_payment_meta' ) ) ) {
104
+ add_filter( 'woocommerce_subscription_payment_meta', array( $this->get_gateway(), 'subscriptions_admin_add_payment_meta' ), 10, 2 );
105
+ }
106
+
107
+ // allow concrete gateways to perform additional validation
108
+ if ( is_callable( array( $this->get_gateway(), 'subscriptions_admin_validate_payment_meta' ) ) ) {
109
+ add_action( 'woocommerce_subscription_validate_payment_meta_' . $this->get_gateway()->get_id(), array( $this->get_gateway(), 'subscriptions_admin_validate_payment_meta' ), 10 );
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Force tokenization for subscriptions, this can be forced either during checkout
115
+ * or when the payment method for a subscription is being changed
116
+ *
117
+ * @since 3.0.0
118
+ * @see Payment_Gateway::tokenization_forced()
119
+ * @param bool $force_tokenization whether tokenization should be forced
120
+ * @return bool true if tokenization should be forced, false otherwise
121
+ */
122
+ public function maybe_force_tokenization( $force_tokenization ) {
123
+
124
+ // pay page with subscription?
125
+ $pay_page_subscription = false;
126
+ if ( $this->get_gateway()->is_pay_page_gateway() ) {
127
+
128
+ $order_id = $this->get_gateway()->get_checkout_pay_page_order_id();
129
+
130
+ if ( $order_id ) {
131
+ $pay_page_subscription = wcs_order_contains_subscription( $order_id );
132
+ }
133
+ }
134
+
135
+ if ( \WC_Subscriptions_Cart::cart_contains_subscription() ||
136
+ wcs_cart_contains_renewal() ||
137
+ \WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment ||
138
+ $pay_page_subscription ) {
139
+ $force_tokenization = true;
140
+ }
141
+
142
+ return $force_tokenization;
143
+ }
144
+
145
+
146
+ /**
147
+ * Save payment meta to the Subscription object after a successful transaction,
148
+ * this is primarily used for the payment token and customer ID which are then
149
+ * copied over to a renewal order prior to payment processing.
150
+ *
151
+ * @since 3.0.0
152
+ * @param \WC_Order $order order
153
+ */
154
+ public function save_payment_meta( $order ) {
155
+
156
+ // a single order can contain multiple subscriptions
157
+ $subscriptions = wcs_get_subscriptions_for_order( Order_Compatibility::get_prop( $order, 'id' ), array(
158
+ 'order_type' => array( 'any' ),
159
+ ) );
160
+
161
+ foreach ( $subscriptions as $subscription ) {
162
+
163
+ // payment token
164
+ if ( ! empty( $order->payment->token ) ) {
165
+ update_post_meta( Order_Compatibility::get_prop( $subscription, 'id' ), $this->get_gateway()->get_order_meta_prefix() . 'payment_token', $order->payment->token );
166
+ }
167
+
168
+ // customer ID
169
+ if ( ! empty( $order->customer_id ) ) {
170
+ update_post_meta( Order_Compatibility::get_prop( $subscription, 'id' ), $this->get_gateway()->get_order_meta_prefix() . 'customer_id', $order->customer_id );
171
+ }
172
+ }
173
+ }
174
+
175
+
176
+ /**
177
+ * Process a subscription renewal payment
178
+ *
179
+ * @since 3.0.0
180
+ * @param float $amount_to_charge subscription amount to charge, could include multiple renewals if they've previously failed and the admin has enabled it
181
+ * @param \WC_Order $order original order containing the subscription
182
+ */
183
+ public function process_renewal_payment( $amount_to_charge, $order ) {
184
+
185
+ // set payment total so it can override the default in get_order()
186
+ $this->renewal_payment_total = Square_Helper::number_format( $amount_to_charge );
187
+
188
+ $token = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'payment_token' );
189
+
190
+ // payment token must be present and valid
191
+ if ( empty( $token ) || ! $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $token ) ) {
192
+
193
+ $this->get_gateway()->mark_order_as_failed( $order, esc_html__( 'Subscription Renewal: payment token is missing/invalid.', 'woocommerce-square' ) );
194
+
195
+ return;
196
+ }
197
+
198
+ // add subscriptions data to the order object prior to processing the payment
199
+ add_filter( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_get_order', array( $this, 'get_order' ) );
200
+
201
+ $this->get_gateway()->process_payment( Order_Compatibility::get_prop( $order, 'id' ) );
202
+ }
203
+
204
+
205
+ /**
206
+ * Adds subscriptions data to the order object, currently:
207
+ *
208
+ * + renewal order specific description
209
+ * + renewal payment total
210
+ * + token and associated data (last four, type, etc)
211
+ *
212
+ * @since 3.0.0
213
+ * @see Payment_Gateway_Direct::get_order()
214
+ * @param \WC_Order $order renewal order
215
+ * @return \WC_Order renewal order with payment token data set
216
+ */
217
+ public function get_order( $order ) {
218
+
219
+ $order->description = sprintf( esc_html__( '%1$s - Subscription Renewal Order %2$s', 'woocommerce-square' ), wp_specialchars_decode( Square_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() );
220
+
221
+ // override the payment total with the amount to charge given by Subscriptions
222
+ $order->payment_total = $this->renewal_payment_total;
223
+
224
+ // set payment token
225
+ $order->payment->token = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'payment_token' );
226
+
227
+ // use customer ID from renewal order, not user meta so the admin can update the customer ID for a subscription if needed
228
+ $customer_id = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'customer_id' );
229
+
230
+ // only if a customer ID exists in order meta, otherwise this will default to the previously set value from user meta
231
+ if ( ! empty( $customer_id ) ) {
232
+ $order->customer_id = $customer_id;
233
+ }
234
+
235
+ // get the token object
236
+ $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token );
237
+
238
+ // set token data on the order
239
+ $order->payment->account_number = $token->get_last_four();
240
+ $order->payment->last_four = $token->get_last_four();
241
+
242
+ if ( $token->is_credit_card() ) {
243
+
244
+ $order->payment->card_type = $token->get_card_type();
245
+ $order->payment->exp_month = $token->get_exp_month();
246
+ $order->payment->exp_year = $token->get_exp_year();
247
+
248
+ }
249
+
250
+ return $order;
251
+ }
252
+
253
+
254
+ /**
255
+ * Don't copy order-specific meta to renewal orders from the WC_Subscription
256
+ * object. Generally the subscription object should not have any order-specific
257
+ * meta (aside from `payment_token` and `customer_id`) as they are not
258
+ * copied during the upgrade (see do_not_copy_order_meta_during_upgrade()), so
259
+ * this method is more of a fallback in case meta accidentally is copied.
260
+ *
261
+ * @since 3.0.0
262
+ * @param array $order_meta order meta to copy
263
+ * @return array
264
+ */
265
+ public function do_not_copy_order_meta( $order_meta ) {
266
+
267
+ $meta_keys = $this->get_order_specific_meta_keys();
268
+
269
+ foreach ( $order_meta as $index => $meta ) {
270
+
271
+ if ( in_array( $meta['meta_key'], $meta_keys, true ) ) {
272
+ unset( $order_meta[ $index ] );
273
+ }
274
+ }
275
+
276
+ return $order_meta;
277
+ }
278
+
279
+
280
+ /**
281
+ * Don't copy order-specific meta to the new WC_Subscription object during
282
+ * upgrade to 2.0.x. This only allows the `payment_token` and `customer_id`
283
+ * meta to be copied.
284
+ *
285
+ * @since 3.0.0
286
+ * @param array $order_meta order meta to copy
287
+ * @return array
288
+ */
289
+ public function do_not_copy_order_meta_during_upgrade( $order_meta ) {
290
+
291
+ foreach ( $this->get_order_specific_meta_keys() as $meta_key ) {
292
+
293
+ if ( isset( $order_meta[ $meta_key ] ) ) {
294
+ unset( $order_meta[ $meta_key ] );
295
+ }
296
+ }
297
+
298
+ return $order_meta;
299
+ }
300
+
301
+
302
+ /**
303
+ * Processes a Change Payment transaction.
304
+ *
305
+ * This hooks in before standard payment processing to simply add or create
306
+ * token data and avoid certain failure conditions affecting the subscription
307
+ * object.
308
+ *
309
+ * @internal
310
+ *
311
+ * @since 3.0.0
312
+ *
313
+ * @param bool|array $result result from any others filtering this
314
+ * @param int $order_id an order or subscription ID
315
+ * @param Payment_Gateway_Direct $gateway gateway object
316
+ * @return array $result change payment result
317
+ */
318
+ public function process_change_payment( $result, $order_id, $gateway ) {
319
+
320
+ // if this is not a subscription and not changing payment, bail for normal order processing
321
+ if ( ! wcs_is_subscription( $order_id ) || ! did_action( 'woocommerce_subscription_change_payment_method_via_pay_shortcode' ) ) {
322
+ return $result;
323
+ }
324
+
325
+ $subscription = $gateway->get_order( $order_id );
326
+
327
+ try {
328
+
329
+ // if using a saved method, just add the data
330
+ if ( isset( $subscription->payment->token ) && $subscription->payment->token ) {
331
+
332
+ $gateway->add_transaction_data( $subscription );
333
+
334
+ // otherwise...tokenize
335
+ } else {
336
+
337
+ $subscription = $gateway->get_payment_tokens_handler()->create_token( $subscription );
338
+ }
339
+
340
+ $result = array(
341
+ 'result' => 'success',
342
+ 'redirect' => $subscription->get_view_order_url(),
343
+ );
344
+
345
+ } catch ( \Exception $e ) {
346
+
347
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - error message; e.g. Order Note: [Payment method] Payment Change failed [error] */
348
+ $note = sprintf( esc_html__( '%1$s Payment Change Failed (%2$s)', 'woocommerce-square' ), $gateway->get_method_title(), $e->getMessage() );
349
+
350
+ // add a subscription note to keep track of failures
351
+ $subscription->add_order_note( $note );
352
+
353
+ Square_Helper::wc_add_notice( esc_html__( 'An error occurred, please try again or try an alternate form of payment.', 'woocommerce-square' ), 'error' );
354
+
355
+ // this isn't used by Subscriptions, but return a failure result anyway
356
+ $result = array(
357
+ 'result' => 'failure',
358
+ 'message' => $e->getMessage(),
359
+ );
360
+ }
361
+
362
+ return $result;
363
+ }
364
+
365
+
366
+ /**
367
+ * Remove order meta (like trans ID) that's added to a Subscription object
368
+ * during the change payment method flow, which uses WC_Payment_Gateway::process_payment(),
369
+ * thus some order-specific meta is added that is undesirable to have copied
370
+ * over to renewal orders.
371
+ *
372
+ * @since 3.0.0
373
+ * @param array $result process_payment() result, unused
374
+ * @param \WC_Subscription $subscription subscription object
375
+ * @return array
376
+ */
377
+ public function remove_order_meta_from_change_payment( $result, $subscription ) {
378
+
379
+ // remove order-specific meta
380
+ foreach ( $this->get_order_specific_meta_keys() as $meta_key ) {
381
+ delete_post_meta( Order_Compatibility::get_prop( $subscription, 'id' ), $meta_key );
382
+ }
383
+
384
+ // get a fresh subscription object after previous metadata changes
385
+ $subscription = wcs_get_subscription( Order_Compatibility::get_prop( $subscription, 'id' ) );
386
+
387
+ $old_payment_method = Order_Compatibility::get_meta( $subscription, '_old_payment_method' );
388
+ $new_payment_method = Order_Compatibility::get_prop( $subscription, 'payment_method' );
389
+
390
+ // if the payment method has been changed to another gateway, additionally remove the old payment token and customer ID meta
391
+ if ( $new_payment_method !== $this->get_gateway()->get_id() && $old_payment_method === $this->get_gateway()->get_id() ) {
392
+ $this->get_gateway()->delete_order_meta( $subscription, 'payment_token' );
393
+ $this->get_gateway()->delete_order_meta( $subscription, 'customer_id' );
394
+ }
395
+
396
+ return $result;
397
+ }
398
+
399
+
400
+ /**
401
+ * Update the payment token and optional customer ID for a subscription after a customer
402
+ * uses this gateway to successfully complete the payment for an automatic
403
+ * renewal payment which had previously failed.
404
+ *
405
+ * @since 3.0.0
406
+ * @param \WC_Subscription $subscription subscription being updated
407
+ * @param \WC_Order $renewal_order order which recorded the successful payment (to make up for the failed automatic payment).
408
+ */
409
+ public function update_failing_payment_method( $subscription, $renewal_order ) {
410
+
411
+ // if the order doesn't have a transaction date stored, bail
412
+ // this prevents updating the subscription with a failing token in case the merchant is switching the order status manually without new payment
413
+ if ( ! $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $renewal_order, 'id' ), 'trans_date' ) ) {
414
+ return;
415
+ }
416
+
417
+ if ( $customer_id = $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $renewal_order, 'id' ), 'customer_id' ) ) {
418
+ $this->get_gateway()->update_order_meta( $subscription, 'customer_id', $customer_id );
419
+ }
420
+
421
+ $this->get_gateway()->update_order_meta( $subscription, 'payment_token', $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $renewal_order, 'id' ), 'payment_token' ) );
422
+ }
423
+
424
+
425
+ /**
426
+ * Get the order-specific meta keys that should not be copied to the WC_Subscription
427
+ * object during upgrade to 2.0.x or during change payment method actions
428
+ *
429
+ * @since 3.0.0
430
+ * @return array
431
+ */
432
+ protected function get_order_specific_meta_keys() {
433
+
434
+ $keys = array(
435
+ 'trans_id',
436
+ 'trans_date',
437
+ 'account_four',
438
+ 'card_expiry_date',
439
+ 'card_type',
440
+ 'authorization_code',
441
+ 'auth_can_be_captured',
442
+ 'charge_captured',
443
+ 'capture_trans_id',
444
+ 'account_type',
445
+ 'check_number',
446
+ 'environment',
447
+ 'retry_count',
448
+ );
449
+
450
+ foreach ( $keys as $index => $key ) {
451
+
452
+ $keys[ $index ] = $this->get_gateway()->get_order_meta_prefix() . $key;
453
+ }
454
+
455
+ /**
456
+ * Filter Subscriptions order-specific meta keys
457
+ *
458
+ * Use this to include additional meta keys that should not be copied over
459
+ * to the WC_Subscriptions object during renewal payments, the
460
+ * change payment method action, or the upgrade to 2.0.x.
461
+ *
462
+ * @since 3.0.0
463
+ * @param array $keys meta keys, with gateway order meta prefix included
464
+ * @param \Payment_Gateway_Integration_Subscriptions $this subscriptions integration class instance
465
+ */
466
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_subscriptions_order_specific_meta_keys', $keys, $this );
467
+ }
468
+
469
+
470
+ /**
471
+ * Render the payment method used for a subscription in the "My Subscriptions" table
472
+ *
473
+ * @since 3.0.0
474
+ * @param string $payment_method_to_display the default payment method text to display
475
+ * @param \WC_Subscription $subscription
476
+ * @return string the subscription payment method
477
+ */
478
+ public function maybe_render_payment_method( $payment_method_to_display, $subscription ) {
479
+
480
+ // bail for other payment methods
481
+ if ( $this->get_gateway()->get_id() !== Order_Compatibility::get_prop( $subscription, 'payment_method' ) ) {
482
+ return $payment_method_to_display;
483
+ }
484
+
485
+ $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $subscription->get_user_id(), $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $subscription, 'id' ), 'payment_token' ) );
486
+
487
+ if ( $token instanceof Payment_Gateway_Payment_Token ) {
488
+ $payment_method_to_display = sprintf( esc_html__( 'Via %s ending in %s', 'woocommerce-square' ), $token->get_type_full(), $token->get_last_four() );
489
+ }
490
+
491
+ return $payment_method_to_display;
492
+ }
493
+
494
+
495
+ /**
496
+ * Add a subscriptions header to the My Payment Methods table.
497
+ *
498
+ * @since 3.0.0
499
+ * @param array $headers the table headers
500
+ * @param \Payment_Gateway_My_Payment_Methods the my payment methods instance
501
+ * @return array
502
+ */
503
+ public function add_my_payment_methods_table_header( $headers, $handler ) {
504
+
505
+ if ( isset( $headers['subscriptions'] ) ) {
506
+ return $headers;
507
+ }
508
+
509
+ $new_headers = array();
510
+
511
+ foreach ( $headers as $id => $label ) {
512
+
513
+ // Add the header before the actions
514
+ if ( 'actions' === $id ) {
515
+ $new_headers['subscriptions'] = esc_html__( 'Subscriptions', 'woocommerce-square' );
516
+ }
517
+
518
+ $new_headers[ $id ] = $label;
519
+ }
520
+
521
+ return $new_headers;
522
+ }
523
+
524
+
525
+ /**
526
+ * Add a subscriptions header to the My Payment Methods table.
527
+ *
528
+ * @since 3.0.0
529
+ * @param array $method the table row data
530
+ * @param \Payment_Gateway_Payment_Token $token the payment token
531
+ * @param \Payment_Gateway_My_Payment_Methods the my payment methods instance
532
+ * @return array
533
+ */
534
+ public function add_my_payment_methods_table_body_row_data( $method, $token, $handler ) {
535
+
536
+ // If the subscription data has already been added or this method is for a different gateway, bail
537
+ if ( isset( $method['subscriptions'] ) || str_replace( '_', '-', $token->get_type() ) !== $this->get_gateway()->get_payment_type() ) {
538
+ return $method;
539
+ }
540
+
541
+ $subscription_ids = array();
542
+
543
+ // Build a link for each subscription
544
+ foreach ( $this->get_payment_token_subscriptions( get_current_user_id(), $token ) as $subscription ) {
545
+ $subscription_ids[] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $subscription->get_view_order_url() ), esc_attr( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-square' ), $subscription->get_order_number() ) ) );
546
+ }
547
+
548
+ if ( ! empty( $subscription_ids ) ) {
549
+ $method['subscriptions'] = implode( ', ', $subscription_ids );
550
+ }
551
+
552
+ return $method;
553
+ }
554
+
555
+
556
+ /**
557
+ * Disables the "Delete" My Payment Methods method action button if there is an associated subscription.
558
+ *
559
+ * @since 3.0.0
560
+ *
561
+ * @param array $actions the token actions
562
+ * @param Payment_Gateway_Payment_Token the token object
563
+ * @param Payment_Gateway_My_Payment_Methods the my payment methods instance
564
+ * @return array
565
+ */
566
+ public function disable_my_payment_methods_table_method_delete( $actions, $token, $handler ) {
567
+
568
+ $disable_delete = false;
569
+
570
+ $subscriptions = $this->get_payment_token_subscriptions( get_current_user_id(), $token );
571
+
572
+ // Check each subscription for the ability to change the payment method
573
+ foreach ( $subscriptions as $subscription ) {
574
+
575
+ if ( $subscription->can_be_updated_to( 'new-payment-method' ) ) {
576
+ $disable_delete = true;
577
+ break;
578
+ }
579
+ }
580
+
581
+ // if at least one can be changed, no deleting for you!
582
+ if ( isset( $actions['delete'] ) && $disable_delete ) {
583
+ $actions['delete']['class'] = array_merge( (array) $actions['delete']['class'], array( 'disabled' ) );
584
+ $actions['delete']['tip'] = esc_html__( 'This payment method is tied to a subscription and cannot be deleted. Please switch the subscription to another method first.', 'woocommerce-square' );
585
+ }
586
+
587
+ return $actions;
588
+ }
589
+
590
+
591
+ /**
592
+ * Gets the subscriptions tied to a user payment token.
593
+ *
594
+ * @since 3.0.0
595
+ *
596
+ * @param int $user_id the user
597
+ * @param Payment_Gateway_Payment_Token the token object
598
+ * @return array the subscriptions or an empty array
599
+ */
600
+ protected function get_payment_token_subscriptions( $user_id, $token ) {
601
+
602
+ $subscriptions = wcs_get_users_subscriptions( $user_id );
603
+
604
+ foreach ( $subscriptions as $key => $subscription ) {
605
+
606
+ $payment_method = Order_Compatibility::get_prop( $subscription, 'payment_method' );
607
+ $stored_token_id = (string) $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $subscription, 'id' ), 'payment_token' );
608
+
609
+ if ( $stored_token_id !== (string) $token->get_id() || $payment_method !== $this->get_gateway()->get_id() ) {
610
+ unset( $subscriptions[ $key ] );
611
+ }
612
+ }
613
+
614
+ return $subscriptions;
615
+ }
616
+
617
+
618
+ /**
619
+ * Include the payment meta data required to process automatic recurring
620
+ * payments so that store managers can manually set up automatic recurring
621
+ * payments for a customer via the Edit Subscriptions screen in 2.0.x
622
+ *
623
+ * @since 3.0.0
624
+ * @param array $meta associative array of meta data required for automatic payments
625
+ * @param \WC_Subscription $subscription subscription object
626
+ * @return array
627
+ */
628
+ public function admin_add_payment_meta( $meta, $subscription ) {
629
+
630
+ $prefix = $this->get_gateway()->get_order_meta_prefix();
631
+
632
+ $meta[ $this->get_gateway()->get_id() ] = array(
633
+ 'post_meta' => array(
634
+ $prefix . 'payment_token' => array(
635
+ 'value' => $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $subscription, 'id' ), 'payment_token' ),
636
+ 'label' => esc_html__( 'Payment Token', 'woocommerce-square' ),
637
+ ),
638
+ $prefix . 'customer_id' => array(
639
+ 'value' => $this->get_gateway()->get_order_meta( Order_Compatibility::get_prop( $subscription, 'id' ), 'customer_id' ),
640
+ 'label' => esc_html__( 'Customer ID', 'woocommerce-square' ),
641
+ ),
642
+ )
643
+ );
644
+
645
+ return $meta;
646
+ }
647
+
648
+
649
+ /**
650
+ * Validate the payment meta data required to process automatic recurring
651
+ * payments so that store managers can manually set up automatic recurring
652
+ * payments for a customer via the Edit Subscriptions screen in 2.0.x
653
+ *
654
+ * @since 3.0.0
655
+ *
656
+ * @param array $meta associative array of meta data required for automatic payments
657
+ * @throws \Exception if payment token or customer ID is missing or blank
658
+ */
659
+ public function admin_validate_payment_meta( $meta ) {
660
+
661
+ $prefix = $this->get_gateway()->get_order_meta_prefix();
662
+
663
+ // payment token
664
+ if ( empty( $meta['post_meta'][ $prefix . 'payment_token' ]['value'] ) ) {
665
+ throw new \Exception( sprintf( esc_html__( '%s is required.', 'woocommerce-square' ), $meta['post_meta'][ $prefix . 'payment_token' ]['label'] ) );
666
+ }
667
+
668
+ // customer ID - optional for some gateways so check if it's set first
669
+ if ( isset( $meta['post_meta'][ $prefix . 'customer_id'] ) && empty( $meta['post_meta'][ $prefix . 'customer_id' ]['value'] ) ) {
670
+ throw new \Exception( sprintf( esc_html__( '%s is required.', 'woocommerce-square' ), $meta['post_meta'][ $prefix . 'customer_id' ]['label'] ) );
671
+ }
672
+ }
673
+ }
includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Token.php ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\PaymentTokens;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ /**
9
+ * WooCommerce Payment Gateway Token
10
+ *
11
+ * Represents a credit card or check payment token
12
+ */
13
+ class Payment_Gateway_Payment_Token {
14
+
15
+
16
+ /** @var string payment gateway token ID */
17
+ protected $id;
18
+
19
+ /**
20
+ * @var array associated token data
21
+ */
22
+ protected $data;
23
+
24
+ /**
25
+ * @var string payment type image url
26
+ */
27
+ protected $img_url;
28
+
29
+
30
+ /**
31
+ * Initialize a payment token with associated $data which is expected to
32
+ * have the following members:
33
+ *
34
+ * default - boolean optional indicates this is the default payment token
35
+ * type - string one of 'credit_card' or 'echeck' ('check' for backwards compatibility)
36
+ * last_four - string last four digits of account number
37
+ * card_type - string credit card type: visa, mc, amex, disc, diners, jcb, etc (credit card only)
38
+ * exp_month - string optional expiration month MM (credit card only)
39
+ * exp_year - string optional expiration year YYYY (credit card only)
40
+ * account_type - string one of 'checking' or 'savings' (checking gateway only)
41
+ *
42
+ * @since 3.0.0
43
+ * @param string $id the payment gateway token ID
44
+ * @param array $data associated data
45
+ */
46
+ public function __construct( $id, $data ) {
47
+
48
+ if ( isset( $data['type'] ) && 'credit_card' == $data['type'] ) {
49
+
50
+ // normalize the provided card type to adjust for possible abbreviations if set
51
+ if ( isset( $data['card_type'] ) && $data['card_type'] ) {
52
+
53
+ $data['card_type'] = Payment_Gateway_Helper::normalize_card_type( $data['card_type'] );
54
+
55
+ // otherwise, get the payment type from the account number
56
+ } elseif ( isset( $data['account_number'] ) ) {
57
+
58
+ $data['card_type'] = Payment_Gateway_Helper::card_type_from_account_number( $data['account_number'] );
59
+ }
60
+ }
61
+
62
+ // remove account number so it's not saved to the token
63
+ unset( $data['account_number'] );
64
+
65
+ $this->id = $id;
66
+ $this->data = $data;
67
+ }
68
+
69
+ /**
70
+ * Returns the payment token string
71
+ *
72
+ * @since 3.0.0
73
+ * @return string payment token string
74
+ */
75
+ public function get_id() {
76
+
77
+ return $this->id;
78
+ }
79
+
80
+
81
+ /**
82
+ * Returns true if this payment token is default
83
+ *
84
+ * @since 3.0.0
85
+ * @return boolean true if this payment token is default
86
+ */
87
+ public function is_default() {
88
+
89
+ return isset( $this->data['default'] ) && $this->data['default'];
90
+ }
91
+
92
+
93
+ /**
94
+ * Makes this payment token the default or a non-default one
95
+ *
96
+ * @since 3.0.0
97
+ * @param boolean $default true or false
98
+ */
99
+ public function set_default( $default ) {
100
+
101
+ $this->data['default'] = $default;
102
+ }
103
+
104
+
105
+ /**
106
+ * Returns true if this payment token represents a credit card
107
+ *
108
+ * @since 3.0.0
109
+ * @return boolean true if this payment token represents a credit card
110
+ */
111
+ public function is_credit_card() {
112
+
113
+ return 'credit_card' == $this->data['type'];
114
+ }
115
+
116
+ /**
117
+ * Returns the payment type, one of 'credit_card' or 'echeck'
118
+ *
119
+ * @since 3.0.0
120
+ * @return string the payment type
121
+ */
122
+ public function get_type() {
123
+
124
+ return $this->data['type'];
125
+ }
126
+
127
+
128
+ /**
129
+ * Returns the card type ie visa, mc, amex, disc, diners, jcb, etc
130
+ *
131
+ * Credit card gateway only
132
+ *
133
+ * @since 3.0.0
134
+ * @return string the payment type
135
+ */
136
+ public function get_card_type() {
137
+
138
+ return isset( $this->data['card_type'] ) ? $this->data['card_type'] : null;
139
+ }
140
+
141
+ /**
142
+ * Returns the bank account type, one of 'checking' or 'savings'
143
+ *
144
+ * eCheck gateway only
145
+ *
146
+ * @since 3.0.0
147
+ * @return string the payment type
148
+ */
149
+ public function get_account_type() {
150
+
151
+ return isset( $this->data['account_type'] ) ? $this->data['account_type'] : null;
152
+ }
153
+
154
+
155
+ /**
156
+ * Set the account type
157
+ *
158
+ * eCheck gateway only
159
+ *
160
+ * @since 3.0.0
161
+ * @param string $account_type
162
+ */
163
+ public function set_account_type( $account_type ) {
164
+
165
+ $this->data['account_type'] = $account_type;
166
+ }
167
+
168
+
169
+ /**
170
+ * Returns the full payment type, ie Visa, MasterCard, American Express,
171
+ * Discover, Diners, JCB, eCheck, etc
172
+ *
173
+ * @since 3.0.0
174
+ * @return string the payment type
175
+ */
176
+ public function get_type_full() {
177
+
178
+ if ( $this->is_credit_card() ) {
179
+ $type = $this->get_card_type() ? $this->get_card_type() : 'card';
180
+ } else {
181
+ $type = $this->get_account_type() ? $this->get_account_type() : 'bank';
182
+ }
183
+
184
+ return Payment_Gateway_Helper::payment_type_to_name( $type );
185
+ }
186
+
187
+
188
+ /**
189
+ * Returns the last four digits of the credit card or check account number
190
+ *
191
+ * @since 3.0.0
192
+ * @return string last four of account
193
+ */
194
+ public function get_last_four() {
195
+
196
+ return isset( $this->data['last_four'] ) ? $this->data['last_four'] : null;
197
+ }
198
+
199
+
200
+ /**
201
+ * Set the account last four
202
+ *
203
+ * @since 3.0.0
204
+ * @param string $last_four
205
+ */
206
+ public function set_last_four( $last_four ) {
207
+
208
+ $this->data['last_four'] = $last_four;
209
+ }
210
+
211
+
212
+ /**
213
+ * Returns the expiration month of the credit card. This should only be
214
+ * called for credit card tokens
215
+ *
216
+ * @since 3.0.0
217
+ * @return string expiration month as a two-digit number
218
+ */
219
+ public function get_exp_month() {
220
+
221
+ return isset( $this->data['exp_month'] ) ? $this->data['exp_month'] : null;
222
+ }
223
+
224
+
225
+ /**
226
+ * Set the expiration month
227
+ *
228
+ * @since 3.0.0
229
+ * @param string $month
230
+ */
231
+ public function set_exp_month( $month ) {
232
+
233
+ $this->data['exp_month'] = $month;
234
+ }
235
+
236
+
237
+ /**
238
+ * Returns the expiration year of the credit card. This should only be
239
+ * called for credit card tokens
240
+ *
241
+ * @since 3.0.0
242
+ * @return string expiration year as a four-digit number
243
+ */
244
+ public function get_exp_year() {
245
+
246
+ return isset( $this->data['exp_year'] ) ? $this->data['exp_year'] : null;
247
+ }
248
+
249
+
250
+ /**
251
+ * Set the expiration year
252
+ *
253
+ * @since 3.0.0
254
+ * @param string $year
255
+ */
256
+ public function set_exp_year( $year ) {
257
+
258
+ $this->data['exp_year'] = $year;
259
+ }
260
+
261
+
262
+ /**
263
+ * Returns the expiration date in the format MM/YY, suitable for use
264
+ * in order notes or other customer-facing areas
265
+ *
266
+ * @since 3.0.0
267
+ * @return string formatted expiration date
268
+ */
269
+ public function get_exp_date() {
270
+
271
+ return $this->get_exp_month() . '/' . substr( $this->get_exp_year(), -2 );
272
+ }
273
+
274
+
275
+ /**
276
+ * Set the full image URL based on the token payment type. Note that this
277
+ * is available for convenience during a single request and will not be
278
+ * included in persistent storage
279
+ *
280
+ * @see Payment_Gateway_Payment_Token::get_image_url()
281
+ * @since 3.0.0
282
+ * @param string $url the full image URL
283
+ */
284
+ public function set_image_url( $url ) {
285
+
286
+ $this->img_url = $url;
287
+ }
288
+
289
+
290
+ /**
291
+ * Get the full image URL based on teh token payment type.
292
+ *
293
+ * @see Payment_Gateway_Payment_Token::set_image_url()
294
+ * @since 3.0.0
295
+ * @return string the full image URL
296
+ */
297
+ public function get_image_url() {
298
+
299
+ return $this->img_url;
300
+ }
301
+
302
+
303
+ /**
304
+ * Gets the payment method nickname.
305
+ *
306
+ * @since 3.0.0
307
+ *
308
+ * @return string
309
+ */
310
+ public function get_nickname() {
311
+
312
+ return isset( $this->data['nickname'] ) ? $this->data['nickname'] : '';
313
+ }
314
+
315
+
316
+ /**
317
+ * Sets the payment method nickname.
318
+ *
319
+ * @since 3.0.0
320
+ *
321
+ * @param string $value nickname value
322
+ */
323
+ public function set_nickname( $value ) {
324
+
325
+ $this->data['nickname'] = $value;
326
+ }
327
+
328
+
329
+ /**
330
+ * Gets the billing address hash.
331
+ *
332
+ * @since 3.0.0
333
+ *
334
+ * @return string
335
+ */
336
+ public function get_billing_hash() {
337
+
338
+ return isset( $this->data['billing_hash'] ) ? $this->data['billing_hash'] : '';
339
+ }
340
+
341
+
342
+ /**
343
+ * Sets the billing hash.
344
+ *
345
+ * @since 3.0.0
346
+ *
347
+ * @param string $value billing hash
348
+ */
349
+ public function set_billing_hash( $value ) {
350
+
351
+ $this->data['billing_hash'] = $value;
352
+ }
353
+
354
+
355
+ /**
356
+ * Returns a representation of this token suitable for persisting to a
357
+ * datastore
358
+ *
359
+ * @since 3.0.0
360
+ * @return mixed datastore representation of token
361
+ */
362
+ public function to_datastore_format() {
363
+
364
+ return $this->data;
365
+ }
366
+ }
includes/Framework/PaymentGateway/PaymentTokens/Payment_Gateway_Payment_Tokens_Handler.php ADDED
@@ -0,0 +1,859 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway\PaymentTokens;
4
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway;
5
+ use WooCommerce\Square\Framework\Addresses\Customer_Address;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Response;
8
+ use WooCommerce\Square\Framework\PaymentGateway\Admin\Payment_Gateway_Admin_Payment_Token_Editor;
9
+
10
+ defined( 'ABSPATH' ) or exit;
11
+
12
+ /**
13
+ * Handle the payment tokenization related functionality.
14
+ *
15
+ * @since 3.0.0
16
+ */
17
+ class Payment_Gateway_Payment_Tokens_Handler {
18
+
19
+ /** @var string the gateway environment ID */
20
+ protected $environment_id;
21
+
22
+ /** @var array|Payment_Gateway_Payment_Token[] array of cached user id to array of Payment_Gateway_Payment_Token token objects */
23
+ protected $tokens;
24
+
25
+ /** @var Payment_Gateway gateway instance */
26
+ protected $gateway;
27
+
28
+
29
+ /**
30
+ * Build the class.
31
+ *
32
+ * @since 3.0.0
33
+ *
34
+ * @param Payment_Gateway $gateway payment gateway instance
35
+ */
36
+ public function __construct( Payment_Gateway $gateway ) {
37
+
38
+ $this->gateway = $gateway;
39
+
40
+ $this->environment_id = $gateway->get_environment();
41
+ }
42
+
43
+
44
+ /**
45
+ * A factory method to build and return a payment token object for the
46
+ * gateway. Concrete classes can override this method to return a custom
47
+ * payment token implementation.
48
+ *
49
+ * @since 3.0.0
50
+ *
51
+ * @param string $token payment token
52
+ * @param array $data {
53
+ * Payment token data.
54
+ *
55
+ * @type bool $default Optional. Indicates this is the default payment token
56
+ * @type string $type Payment type. Either 'credit_card' or 'check'
57
+ * @type string $last_four Last four digits of account number
58
+ * @type string $card_type Credit card type (`visa`, `mc`, `amex`, `disc`, `diners`, `jcb`) or `echeck`
59
+ * @type string $exp_month Optional. Expiration month (credit card only)
60
+ * @type string $exp_year Optional. Expiration year (credit card only)
61
+ * }
62
+ * @return Payment_Gateway_Payment_Token payment token
63
+ */
64
+ public function build_token( $token, $data ) {
65
+
66
+ return new Payment_Gateway_Payment_Token( $token, $data );
67
+ }
68
+
69
+
70
+ /** Handle single tokens **********************************************************************/
71
+
72
+
73
+ /**
74
+ * Tokenizes the current payment method and adds the standard transaction
75
+ * data to the order post record.
76
+ *
77
+ * @since 3.0.0
78
+ *
79
+ * @param \WC_Order $order order object
80
+ * @param Payment_Gateway_API_Create_Payment_Token_Response|null $response payment token API response, or null if the request should be made
81
+ * @param string $environment_id optional environment ID, defaults to the current environment
82
+ * @return \WC_Order order object
83
+ * @throws \Exception on transaction failure
84
+ */
85
+ public function create_token( \WC_Order $order, $response = null, $environment_id = null ) {
86
+ $gateway = $this->get_gateway();
87
+ // default to current environment
88
+ if ( is_null( $environment_id ) ) {
89
+ $environment_id = $this->get_environment_id();
90
+ }
91
+
92
+ // perform the API request to tokenize the payment method if needed
93
+ if ( ! $response || $this->get_gateway()->tokenize_after_sale() ) {
94
+ $response = $gateway->get_api()->tokenize_payment_method( $order );
95
+ }
96
+
97
+ if ( $response->transaction_approved() ) {
98
+
99
+ // add the token to the order object for processing
100
+ $token = $response->get_payment_token();
101
+ $address = new Customer_Address();
102
+
103
+ // generate an address from the order
104
+ $address->set_from_order( $order );
105
+
106
+ // store the billing hash on the token for later use in case it needs to be updated
107
+ $token->set_billing_hash( $address->get_hash() );
108
+
109
+ // set the resulting token on the order
110
+ $order->payment->token = $token->get_id();
111
+
112
+ // for credit card transactions add the card type, if known (some gateways return the credit card type as part of the response, others may require it as part of the request, and still others it may never be known)
113
+ if ( $gateway->is_credit_card_gateway() && $token->get_card_type() ) {
114
+ $order->payment->card_type = $token->get_card_type();
115
+ }
116
+
117
+ // set the token to the user account
118
+ if ( $order->get_user_id() ) {
119
+ $this->add_token( $order->get_user_id(), $token, $environment_id );
120
+ }
121
+
122
+ $order->add_order_note( $this->get_order_note( $token ) );
123
+
124
+ // add the standard transaction data
125
+ $gateway->add_transaction_data( $order, $response );
126
+
127
+ // clear any cached tokens
128
+ if ( $transient_key = $this->get_transient_key( $order->get_user_id() ) ) {
129
+ delete_transient( $transient_key );
130
+ }
131
+
132
+ } else {
133
+
134
+ if ( $response->get_status_code() && $response->get_status_message() ) {
135
+ /* translators: Placeholders: %1$s - payment request response status code, %2$s - payment request response status message */
136
+ $message = sprintf( esc_html__( 'Status code %1$s: %2$s', 'woocommerce-square' ), $response->get_status_code(), $response->get_status_message() );
137
+ } elseif ( $response->get_status_code() ) {
138
+ /* translators: Placeholders: %s - payment request response status code */
139
+ $message = sprintf( esc_html__( 'Status code: %s', 'woocommerce-square' ), $response->get_status_code() );
140
+ } elseif ( $response->get_status_message() ) {
141
+ /* translators: Placeholders: %s - payment request response status message */
142
+ $message = sprintf( esc_html__( 'Status message: %s', 'woocommerce-square' ), $response->get_status_message() );
143
+ } else {
144
+ $message = esc_html__( 'Unknown Error', 'woocommerce-square' );
145
+ }
146
+
147
+ // add transaction id if there is one
148
+ if ( $response->get_transaction_id() ) {
149
+ $message .= ' ' . sprintf( esc_html__( 'Transaction ID %s', 'woocommerce-square' ), $response->get_transaction_id() );
150
+ }
151
+
152
+ throw new \Exception( $message );
153
+ }
154
+
155
+ return $order;
156
+ }
157
+
158
+
159
+ /**
160
+ * Adds a payment method and token as user meta.
161
+ *
162
+ * @since 3.0.0
163
+ *
164
+ * @param int $user_id user identifier
165
+ * @param Payment_Gateway_Payment_Token $token the token
166
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
167
+ * @return bool|int false if token not added, user meta ID if added
168
+ */
169
+ public function add_token( $user_id, $token, $environment_id = null ) {
170
+
171
+ // default to current environment
172
+ if ( is_null( $environment_id ) ) {
173
+ $environment_id = $this->get_environment_id();
174
+ }
175
+
176
+ // get existing tokens
177
+ $tokens = $this->get_tokens( $user_id, array( 'environment_id' => $environment_id ) );
178
+
179
+ // if this token is set as active, mark all others as false
180
+ if ( $token->is_default() ) {
181
+ foreach ( array_keys( $tokens ) as $key ) {
182
+ $tokens[ $key ]->set_default( false );
183
+ }
184
+ }
185
+
186
+ // add the new token
187
+ $tokens[ $token->get_id() ] = $token;
188
+
189
+ // persist the updated tokens
190
+ return $this->update_tokens( $user_id, $tokens, $environment_id );
191
+ }
192
+
193
+
194
+ /**
195
+ * Returns the payment token object identified by $token from the user
196
+ * identified by $user_id
197
+ *
198
+ * @since 3.0.0
199
+ *
200
+ * @param int $user_id WordPress user identifier, or 0 for guest
201
+ * @param string $token payment token
202
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
203
+ * @return Payment_Gateway_Payment_Token payment token object or null
204
+ */
205
+ public function get_token( $user_id, $token, $environment_id = null ) {
206
+
207
+ // default to current environment
208
+ if ( is_null( $environment_id ) ) {
209
+ $environment_id = $this->get_environment_id();
210
+ }
211
+
212
+ $tokens = $this->get_tokens( $user_id, array( 'environment_id' => $environment_id ) );
213
+
214
+ if ( isset( $tokens[ $token ] ) ) return $tokens[ $token ];
215
+
216
+ return null;
217
+ }
218
+
219
+
220
+ /**
221
+ * Updates a single token by persisting it to user meta
222
+ *
223
+ * @since 3.0.0
224
+ *
225
+ * @param int $user_id WP user ID
226
+ * @param Payment_Gateway_Payment_Token $token token to update
227
+ * @param string|null $environment_id optional environment ID, defaults to plugin current environment
228
+ * @return string|int updated user meta ID
229
+ */
230
+ public function update_token( $user_id, $token, $environment_id = null ) {
231
+
232
+ // default to current environment
233
+ if ( null === $environment_id ) {
234
+ $environment_id = $this->get_environment_id();
235
+ }
236
+
237
+ $tokens = $this->get_tokens( $user_id, array( 'environment_id' => $environment_id ) );
238
+
239
+ if ( isset( $tokens[ $token->get_id() ] ) ) {
240
+ $tokens[ $token->get_id() ] = $token;
241
+ }
242
+
243
+ return $this->update_tokens( $user_id, $tokens, $environment_id );
244
+ }
245
+
246
+
247
+ /**
248
+ * Deletes a credit card token from user meta
249
+ *
250
+ * @since 3.0.0
251
+ *
252
+ * @param int $user_id user identifier
253
+ * @param Payment_Gateway_Payment_Token|string $token the payment token to delete
254
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
255
+ * @return bool|int false if not deleted, updated user meta ID if deleted
256
+ */
257
+ public function remove_token( $user_id, $token, $environment_id = null ) {
258
+
259
+ // default to current environment
260
+ if ( is_null( $environment_id ) ) {
261
+ $environment_id = $this->get_environment_id();
262
+ }
263
+
264
+ // unknown token?
265
+ if ( ! $this->user_has_token( $user_id, $token, $environment_id ) ) {
266
+ return false;
267
+ }
268
+
269
+ // get the payment token object as needed
270
+ if ( ! is_object( $token ) ) {
271
+ $token = $this->get_token( $user_id, $token, $environment_id );
272
+ }
273
+
274
+ // for direct gateways that allow it, attempt to delete the token from the endpoint
275
+ if ( $this->get_gateway()->get_api()->supports_remove_tokenized_payment_method() ) {
276
+
277
+ try {
278
+
279
+ $response = $this->get_gateway()->get_api()->remove_tokenized_payment_method( $token->get_id(), $this->get_gateway()->get_customer_id( $user_id, array( 'environment_id' => $environment_id ) ) );
280
+
281
+ if ( ! $response->transaction_approved() && ! $this->should_delete_token( $token, $response ) ) {
282
+ return false;
283
+ }
284
+
285
+ } catch( \Exception $e ) {
286
+
287
+ if ( $this->get_gateway()->debug_log() ) {
288
+ $this->get_gateway()->get_plugin()->log( $e->getMessage(), $this->get_gateway()->get_id() );
289
+ }
290
+
291
+ return false;
292
+ }
293
+ }
294
+
295
+ return $this->delete_token( $user_id, $token );
296
+ }
297
+
298
+
299
+ /**
300
+ * Determines if a token's local meta should be deleted based on an API response.
301
+ *
302
+ * @since 3.0.0
303
+ *
304
+ * @param Payment_Gateway_Payment_Token $token payment token object
305
+ * @param Payment_Gateway_API_Response $response API response object
306
+ * @return bool
307
+ */
308
+ public function should_delete_token( Payment_Gateway_Payment_Token $token, Payment_Gateway_API_Response $response ) {
309
+ return false;
310
+ }
311
+
312
+
313
+ /**
314
+ * Deletes a payment token from user meta.
315
+ *
316
+ * @since 3.0.0
317
+ *
318
+ * @param int $user_id WordPress user ID
319
+ * @param Payment_Gateway_Payment_Token $token payment token object
320
+ * @param string|null $environment_id gateway environment ID
321
+ * @return bool
322
+ */
323
+ public function delete_token( $user_id, Payment_Gateway_Payment_Token $token, $environment_id = null ) {
324
+
325
+ // default to current environment
326
+ if ( is_null( $environment_id ) ) {
327
+ $environment_id = $this->get_environment_id();
328
+ }
329
+
330
+ // get existing tokens
331
+ $tokens = $this->get_tokens( $user_id, array( 'environment_id' => $environment_id ) );
332
+
333
+ if ( ! isset( $tokens[ $token->get_id() ] ) ) {
334
+ return false;
335
+ }
336
+
337
+ unset( $tokens[ $token->get_id() ] );
338
+
339
+ // if the deleted card was the default one, make another one the new default
340
+ if ( $token->is_default() ) {
341
+
342
+ foreach ( array_keys( $tokens ) as $key ) {
343
+
344
+ $tokens[ $key ]->set_default( true );
345
+ break;
346
+ }
347
+ }
348
+
349
+ // persist the updated tokens
350
+ return $this->update_tokens( $user_id, $tokens );
351
+ }
352
+
353
+
354
+ /**
355
+ * Sets the default token for a user.
356
+ *
357
+ * This is shown as "Default Card" in the frontend and will be auto-selected during checkout.
358
+ *
359
+ * @since 3.0.0
360
+ *
361
+ * @param int $user_id user identifier
362
+ * @param Payment_Gateway_Payment_Token|string $token the token to make default
363
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
364
+ * @return string|bool false if not set, updated user meta ID if set
365
+ */
366
+ public function set_default_token( $user_id, $token, $environment_id = null ) {
367
+
368
+ // default to current environment
369
+ if ( is_null( $environment_id ) ) {
370
+ $environment_id = $this->get_environment_id();
371
+ }
372
+
373
+ // unknown token?
374
+ if ( ! $this->user_has_token( $user_id, $token ) )
375
+ return false;
376
+
377
+ // get the payment token object as needed
378
+ if ( ! is_object( $token ) ) {
379
+ $token = $this->get_token( $user_id, $token, $environment_id );
380
+ }
381
+
382
+ // get existing tokens
383
+ $tokens = $this->get_tokens( $user_id, array( 'environment_id' => $environment_id ) );
384
+
385
+ // mark $token as the only active
386
+ foreach ( $tokens as $key => $_token ) {
387
+
388
+ if ( $token->get_id() == $_token->get_id() ) {
389
+ $tokens[ $key ]->set_default( true );
390
+ } else {
391
+ $tokens[ $key ]->set_default( false );
392
+ }
393
+
394
+ }
395
+
396
+ // persist the updated tokens
397
+ return $this->update_tokens( $user_id, $tokens, $environment_id );
398
+
399
+ }
400
+
401
+
402
+ /** Handle all tokens *************************************************************************/
403
+
404
+
405
+ /**
406
+ * Gets the available payment tokens for a user as an associative array of
407
+ * payment token to Payment_Gateway_Payment_Token
408
+ *
409
+ * @since 3.0.0
410
+ *
411
+ * @param int $user_id WordPress user identifier, or 0 for guest
412
+ * @param array $args optional arguments, can include
413
+ * `customer_id` - if not provided, this will be looked up based on $user_id
414
+ * `environment_id` - defaults to plugin current environment
415
+ * @return array|Payment_Gateway_Payment_Token[] associative array of string token to Payment_Gateway_Payment_Token object
416
+ */
417
+ public function get_tokens( $user_id, $args = array() ) {
418
+
419
+ // default to current environment
420
+ if ( ! isset( $args['environment_id'] ) ) {
421
+ $args['environment_id'] = $this->get_environment_id();
422
+ }
423
+
424
+ if ( ! isset( $args['customer_id'] ) ) {
425
+ $args['customer_id'] = $this->get_gateway()->get_customer_id( $user_id, array( 'environment_id' => $args['environment_id'] ) );
426
+ }
427
+
428
+ $environment_id = $args['environment_id'];
429
+ $customer_id = $args['customer_id'];
430
+ $transient_key = $this->get_transient_key( $user_id );
431
+
432
+ // return tokens cached during a single request
433
+ if ( isset( $this->tokens[ $environment_id ][ $user_id ] ) ) {
434
+ return $this->tokens[ $environment_id ][ $user_id ];
435
+ }
436
+
437
+ // return tokens cached in transient
438
+ if ( $transient_key && ( false !== ( $this->tokens[ $environment_id ][ $user_id ] = get_transient( $transient_key ) ) ) ) {
439
+ return $this->tokens[ $environment_id ][ $user_id ];
440
+ }
441
+
442
+ $this->tokens[ $environment_id ][ $user_id ] = array();
443
+ $tokens = array();
444
+
445
+ // retrieve the datastore persisted tokens first, so we have them for
446
+ // gateways that don't support fetching them over an API, as well as the
447
+ // default token for those that do
448
+ if ( $user_id ) {
449
+
450
+ $_tokens = get_user_meta( $user_id, $this->get_user_meta_name( $environment_id ), true );
451
+
452
+ // from database format
453
+ if ( is_array( $_tokens ) ) {
454
+ foreach ( $_tokens as $token => $data ) {
455
+ $tokens[ $token ] = $this->build_token( $token, $data );
456
+ }
457
+ }
458
+
459
+ $this->tokens[ $environment_id ][ $user_id ] = $tokens;
460
+ }
461
+
462
+ // if the payment gateway API supports retrieving tokens directly, do so as it's easier to stay synchronized
463
+ if ( $this->get_gateway()->get_api()->supports_get_tokenized_payment_methods() && $customer_id ) {
464
+
465
+ try {
466
+
467
+ // retrieve the payment method tokes from the remote API
468
+ $response = $this->get_gateway()->get_api()->get_tokenized_payment_methods( $customer_id );
469
+ $this->tokens[ $environment_id ][ $user_id ] = $response->get_payment_tokens();
470
+
471
+ // check for a default from the persisted set, if any
472
+ $default_token = null;
473
+ foreach ( $tokens as $default_token ) {
474
+ if ( $default_token->is_default() ) {
475
+ break;
476
+ }
477
+ }
478
+
479
+ // mark the corresponding token from the API as the default one
480
+ if ( $default_token && $default_token->is_default() && isset( $this->tokens[ $environment_id ][ $user_id ][ $default_token->get_id() ] ) ) {
481
+ $this->tokens[ $environment_id ][ $user_id ][ $default_token->get_id() ]->set_default( true );
482
+ }
483
+
484
+ // merge local token data with remote data, sometimes local data is more robust
485
+ $this->tokens[ $environment_id ][ $user_id ] = $this->merge_token_data( $tokens, $this->tokens[ $environment_id ][ $user_id ] );
486
+
487
+ // persist locally after merging
488
+ $this->update_tokens( $user_id, $this->tokens[ $environment_id ][ $user_id ], $environment_id );
489
+
490
+ } catch( \Exception $e ) {
491
+
492
+ // communication or other error
493
+
494
+ $this->get_gateway()->add_debug_message( $e->getMessage(), 'error' );
495
+
496
+ $this->tokens[ $environment_id ][ $user_id ] = $tokens;
497
+ }
498
+
499
+ }
500
+
501
+ // set the payment type image url, if any, for convenience
502
+ foreach ( $this->tokens[ $environment_id ][ $user_id ] as $key => $token ) {
503
+ $this->tokens[ $environment_id ][ $user_id ][ $key ]->set_image_url( $this->get_gateway()->get_payment_method_image_url( $token->is_credit_card() ? $token->get_card_type() : 'echeck' ) );
504
+ }
505
+
506
+ if ( $transient_key ) {
507
+ set_transient( $transient_key, $this->tokens[ $environment_id ][ $user_id ], 60 );
508
+ }
509
+
510
+ /**
511
+ * Direct Payment Gateway Payment Tokens Loaded Action.
512
+ *
513
+ * Fired when payment tokens have been completely loaded.
514
+ *
515
+ * @since 3.0.0
516
+ *
517
+ * @param array $tokens array of Payment_Gateway_Payment_Tokens
518
+ * @param Payment_Gateway gateway class instance
519
+ */
520
+ do_action( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_payment_tokens_loaded', $this->tokens[ $environment_id ][ $user_id ], $this );
521
+
522
+ return $this->tokens[ $environment_id ][ $user_id ];
523
+ }
524
+
525
+
526
+ /**
527
+ * Updates the given payment tokens for the identified user, in the database.
528
+ *
529
+ * @since 3.0.0
530
+ *
531
+ * @param int $user_id WP user ID
532
+ * @param array $tokens array of tokens
533
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
534
+ * @return string updated user meta id
535
+ */
536
+ public function update_tokens( $user_id, $tokens, $environment_id = null ) {
537
+
538
+ // default to current environment
539
+ if ( is_null( $environment_id ) ) {
540
+ $environment_id = $this->get_environment_id();
541
+ }
542
+
543
+ // update the local cache
544
+ $this->tokens[ $environment_id ][ $user_id ] = $tokens;
545
+
546
+ // clear the transient
547
+ $this->clear_transient( $user_id );
548
+
549
+ // persist the updated tokens to the user meta
550
+ return update_user_meta( $user_id, $this->get_user_meta_name( $environment_id ), $this->format_for_db( $tokens ) );
551
+ }
552
+
553
+
554
+
555
+ /** Admin methods *****************************************************************************/
556
+
557
+
558
+ /**
559
+ * Get the admin token editor instance.
560
+ *
561
+ * @since 3.0.0
562
+ *
563
+ * @return Payment_Gateway_Admin_Payment_Token_Editor
564
+ */
565
+ public function get_token_editor() {
566
+ return new Payment_Gateway_Admin_Payment_Token_Editor( $this->get_gateway() );
567
+ }
568
+
569
+
570
+ /** Conditional methods ***********************************************************************/
571
+
572
+
573
+ /**
574
+ * Determines if the identified user has the given payment token
575
+ *
576
+ * @since 3.0.0
577
+ *
578
+ * @param int $user_id WordPress user identifier, or 0 for guest
579
+ * @param string|Payment_Gateway_Payment_Token $token payment token
580
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
581
+ * @return bool
582
+ */
583
+ public function user_has_token( $user_id, $token, $environment_id = null ) {
584
+
585
+ // default to current environment
586
+ if ( is_null( $environment_id ) ) {
587
+ $environment_id = $this->get_environment_id();
588
+ }
589
+
590
+ if ( is_object( $token ) ) {
591
+ $token = $token->get_id();
592
+ }
593
+
594
+ // token exists?
595
+ return ! is_null( $this->get_token( $user_id, $token, $environment_id ) );
596
+ }
597
+
598
+
599
+ /**
600
+ * Determines if the current payment method should be tokenized.
601
+ *
602
+ * Whether requested by customer or otherwise forced. This parameter is passed from
603
+ * the checkout page/payment form.
604
+ *
605
+ * @since 3.0.0
606
+ *
607
+ * @return bool
608
+ */
609
+ public function should_tokenize() {
610
+
611
+ return Square_Helper::get_post( 'wc-' . $this->get_gateway()->get_id_dasherized() . '-tokenize-payment-method' ) && ! Square_Helper::get_post( 'wc-' . $this->get_gateway()->get_id_dasherized() . '-payment-token' );
612
+ }
613
+
614
+
615
+ /**
616
+ * Determines if tokenization should be forced on the checkout page.
617
+ *
618
+ * This is most useful to force tokenization for a subscription or pre-orders initial transaction.
619
+ *
620
+ * @since 3.0.0
621
+ *
622
+ * @return bool
623
+ */
624
+ public function tokenization_forced() {
625
+
626
+ /**
627
+ * Direct Gateway Tokenization Forced Filter.
628
+ *
629
+ * Allow actors to indicate that tokenization should be forced for the current
630
+ * checkout.
631
+ *
632
+ * @since 3.0.0
633
+ *
634
+ * @param bool $force true to force tokenization, false otherwise
635
+ * @param Payment_Gateway $this instance
636
+ */
637
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_tokenization_forced', false, $this->get_gateway() );
638
+ }
639
+
640
+
641
+ /** Utility methods ***************************************************************************/
642
+
643
+
644
+ /**
645
+ * Merges remote token data with local tokens.
646
+ *
647
+ * Sometimes local tokens can provide additional detail that's not provided remotely.
648
+ *
649
+ * @since 3.0.0
650
+ *
651
+ * @param array $local_tokens local tokens
652
+ * @param array $remote_tokens remote tokens
653
+ * @return array associative array of string token to Payment_Gateway_Payment_Token objects
654
+ */
655
+ protected function merge_token_data( $local_tokens, $remote_tokens ) {
656
+
657
+ foreach ( $remote_tokens as &$remote_token ) {
658
+
659
+ $remote_token_id = $remote_token->get_id();
660
+
661
+ // bail if the remote token doesn't exist locally
662
+ if ( ! isset( $local_tokens[ $remote_token_id ] ) ) {
663
+ continue;
664
+ }
665
+
666
+ foreach ( $this->get_merge_attributes() as $attribute ) {
667
+
668
+ $get_method = "get_{$attribute}";
669
+ $set_method = "set_{$attribute}";
670
+
671
+ // if the remote token is missing an attribute and the local token has it...
672
+ if ( ! $remote_token->$get_method() && $local_tokens[ $remote_token_id ]->$get_method() ) {
673
+
674
+ // set the attribute on the remote token
675
+ $remote_token->$set_method( $local_tokens[ $remote_token_id ]->$get_method() );
676
+ }
677
+ }
678
+ }
679
+
680
+ return $remote_tokens;
681
+ }
682
+
683
+
684
+ /**
685
+ * Returns the attributes that should be used to merge local token data into
686
+ * a remote token.
687
+ *
688
+ * Gateways can override this method to add their own attributes, but must
689
+ * also include the associated get_*() & set_*() methods in the token class.
690
+ *
691
+ * See Authorize.net CIM for an example implementation.
692
+ *
693
+ * @since 3.0.0
694
+ *
695
+ * @return array associative array of string token to Payment_Gateway_Payment_Token objects
696
+ */
697
+ protected function get_merge_attributes() {
698
+
699
+ return array( 'last_four', 'card_type', 'account_type', 'exp_month', 'exp_year', 'nickname' );
700
+ }
701
+
702
+
703
+ /**
704
+ * Gets the payment token transient key for the given user, gateway and environment.
705
+ *
706
+ * Payment token transients can be disabled by using the filter below.
707
+ *
708
+ * @since 3.0.0
709
+ *
710
+ * @param string|int $user_id
711
+ * @return string transient key
712
+ */
713
+ protected function get_transient_key( $user_id = null ) {
714
+
715
+ if ( ! $user_id ) {
716
+ $user_id = get_current_user_id();
717
+ }
718
+
719
+ // ex: wc_square_tokens_<md5 hash of gateway_id, user ID, and environment ID>
720
+ $key = sprintf( 'wc_square_tokens_%s', md5( $this->get_gateway()->get_id() . '_' . $user_id . '_' . $this->get_environment_id() ) );
721
+
722
+ /**
723
+ * Filter payment tokens transient key
724
+ *
725
+ * Warning: this filter should generally only be used to disable token
726
+ * transients by returning false or an empty string. Setting an incorrect or invalid
727
+ * transient key (e.g. not keyed to the current user or environment) can
728
+ * result in unexpected and difficult to debug situations involving tokens.
729
+ *
730
+ * filter responsibly!
731
+ *
732
+ * @since 3.0.0
733
+ * @param string $key transient key (must be 45 chars or less)
734
+ * @param Payment_Gateway $this direct gateway class instance
735
+ */
736
+ return apply_filters( 'wc_payment_gateway_' . $this->get_gateway()->get_id() . '_payment_tokens_transient_key', $key, $user_id, $this->get_gateway() );
737
+ }
738
+
739
+
740
+ /**
741
+ * Helper method to clear the tokens transient
742
+ *
743
+ * TODO: ideally the transient would make use of actions to clear itself
744
+ * as needed (e.g. when customer IDs are updated/removed), but for now it's
745
+ * only cleared when the tokens are updated. @MR July 2015
746
+ *
747
+ * @since 3.0.0
748
+ *
749
+ * @param int|string $user_id
750
+ */
751
+ public function clear_transient( $user_id ) {
752
+ delete_transient( $this->get_transient_key( $user_id ) );
753
+ }
754
+
755
+
756
+ /**
757
+ * Returns the payment token user meta name for persisting the payment tokens.
758
+ *
759
+ * Defaults to _wc_{gateway id}_payment_tokens for the production environment,
760
+ * and _wc_{gateway id}_payment_tokens_{environment} for any other environment.
761
+ *
762
+ * NOTE: the gateway id, rather than plugin id, is used by default to create
763
+ * the meta key for this setting, because it's assumed that in the case of a
764
+ * plugin having multiple gateways (ie credit card and eCheck) the payment
765
+ * tokens will be distinct between them
766
+ *
767
+ * @since 3.0.0
768
+ *
769
+ * @param string|null $environment_id optional environment id, defaults to plugin current environment
770
+ * @return string payment token user meta name
771
+ */
772
+ public function get_user_meta_name( $environment_id = null ) {
773
+
774
+ // default to current environment
775
+ if ( is_null( $environment_id ) ) {
776
+ $environment_id = $this->get_environment_id();
777
+ }
778
+
779
+ // leading underscore since this will never be displayed to an admin user in its raw form
780
+ return $this->get_gateway()->get_order_meta_prefix() . 'payment_tokens' . ( ! $this->get_gateway()->is_production_environment( $environment_id ) ? '_' . $environment_id : '' );
781
+ }
782
+
783
+
784
+ /**
785
+ * Gets the order note message when a customer saves their payment method
786
+ * to their account
787
+ *
788
+ * @since 3.0.0
789
+ *
790
+ * @param Payment_Gateway_Payment_Token $token the payment token being saved
791
+ * @return string
792
+ */
793
+ protected function get_order_note( $token ) {
794
+
795
+ $gateway = $this->get_gateway();
796
+
797
+ $message = '';
798
+
799
+ // order note based on gateway type
800
+ if ( $gateway->is_credit_card_gateway() ) {
801
+
802
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - payment method name (mastercard, bank account, etc), %3$s - last four digits of the card/account, %4$s - card/account expiry date */
803
+ $message = sprintf( esc_html__( '%1$s Payment Method Saved: %2$s ending in %3$s (expires %4$s)', 'woocommerce-square' ),
804
+ $gateway->get_method_title(),
805
+ $token->get_type_full(),
806
+ $token->get_last_four(),
807
+ $token->get_exp_date()
808
+ );
809
+
810
+ }
811
+
812
+ return $message;
813
+ }
814
+
815
+
816
+ /**
817
+ * Returns $tokens in a format suitable for data storage
818
+ *
819
+ * @since 3.0.0
820
+ *
821
+ * @param array $tokens array of Payment_Gateway_Payment_Token tokens
822
+ * @return array data storage version of $tokens
823
+ */
824
+ protected function format_for_db( $tokens ) {
825
+
826
+ $_tokens = array();
827
+
828
+ // to database format
829
+ foreach ( $tokens as $key => $token ) {
830
+ $_tokens[ $key ] = $token->to_datastore_format();
831
+ }
832
+
833
+ return $_tokens;
834
+ }
835
+
836
+
837
+ /**
838
+ * Get the gateway environment ID.
839
+ *
840
+ * @since 3.0.0
841
+ *
842
+ * @return string
843
+ */
844
+ protected function get_environment_id() {
845
+ return $this->environment_id;
846
+ }
847
+
848
+
849
+ /**
850
+ * Gets the gateway instance.
851
+ *
852
+ * @since 3.0.0
853
+ *
854
+ * @return Payment_Gateway gateway instance
855
+ */
856
+ protected function get_gateway() {
857
+ return $this->gateway;
858
+ }
859
+ }
includes/Framework/PaymentGateway/Payment_Gateway.php ADDED
@@ -0,0 +1,3813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway;
4
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
5
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Authorization_Response;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Response;
8
+ use WooCommerce\Square\Framework\PaymentGateway\ApplePay\Api\Payment_Gateway_Apple_Pay_Payment_Response;
9
+ use WooCommerce\Square\Framework\PaymentGateway\Handlers\Capture;
10
+ use WooCommerce\Square\Framework\PaymentGateway\Integrations\Payment_Gateway_Integration_Pre_Orders;
11
+ use WooCommerce\Square\Framework\PaymentGateway\Integrations\Payment_Gateway_Integration_Subscriptions;
12
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Tokens_Handler;
13
+ use WooCommerce\Square\Plugin;
14
+ use WooCommerce\Square\Framework as SquareFramework;
15
+
16
+ defined( 'ABSPATH' ) or exit;
17
+
18
+ /**
19
+ * WooCommerce Payment Gateway Framework
20
+ *
21
+ * @since 3.0.0
22
+ */
23
+ abstract class Payment_Gateway extends \WC_Payment_Gateway {
24
+
25
+
26
+ /** Sends through sale and request for funds to be charged to cardholder's credit card. */
27
+ const TRANSACTION_TYPE_CHARGE = 'charge';
28
+
29
+ /** Sends through a request for funds to be "reserved" on the cardholder's credit card. A standard authorization is reserved for 2-5 days. Reservation times are determined by cardholder's bank. */
30
+ const TRANSACTION_TYPE_AUTHORIZATION = 'authorization';
31
+
32
+ /** The production environment identifier */
33
+ const ENVIRONMENT_PRODUCTION = 'production';
34
+
35
+ /** The test environment identifier */
36
+ const ENVIRONMENT_TEST = 'test';
37
+
38
+ /** Debug mode log to file */
39
+ const DEBUG_MODE_LOG = 'log';
40
+
41
+ /** Debug mode display on checkout */
42
+ const DEBUG_MODE_CHECKOUT = 'checkout';
43
+
44
+ /** Debug mode log to file and display on checkout */
45
+ const DEBUG_MODE_BOTH = 'both';
46
+
47
+ /** Debug mode disabled */
48
+ const DEBUG_MODE_OFF = 'off';
49
+
50
+ /** Credit card payment type */
51
+ const PAYMENT_TYPE_CREDIT_CARD = 'credit-card';
52
+
53
+ /** Products feature */
54
+ const FEATURE_PRODUCTS = 'products';
55
+
56
+ /** Credit card types feature */
57
+ const FEATURE_CARD_TYPES = 'card_types';
58
+
59
+ /** Tokenization feature */
60
+ const FEATURE_TOKENIZATION = 'tokenization';
61
+
62
+ /** Credit Card charge transaction feature */
63
+ const FEATURE_CREDIT_CARD_CHARGE = 'charge';
64
+
65
+ /** Credit Card authorization transaction feature */
66
+ const FEATURE_CREDIT_CARD_AUTHORIZATION = 'authorization';
67
+
68
+ /** Credit Card charge virtual-only orders feature */
69
+ const FEATURE_CREDIT_CARD_CHARGE_VIRTUAL = 'charge-virtual';
70
+
71
+ /** Credit Card capture charge transaction feature */
72
+ const FEATURE_CREDIT_CARD_CAPTURE = 'capture_charge';
73
+
74
+ /** Credit Card partial capture transaction feature */
75
+ const FEATURE_CREDIT_CARD_PARTIAL_CAPTURE = 'partial_capture';
76
+
77
+ /** Display detailed customer decline messages on checkout */
78
+ const FEATURE_DETAILED_CUSTOMER_DECLINE_MESSAGES = 'customer_decline_messages';
79
+
80
+ /** Refunds feature */
81
+ const FEATURE_REFUNDS = 'refunds';
82
+
83
+ /** Voids feature */
84
+ const FEATURE_VOIDS = 'voids';
85
+
86
+ /** Payment Form feature */
87
+ const FEATURE_PAYMENT_FORM = 'payment_form';
88
+
89
+ /** Customer ID feature */
90
+ const FEATURE_CUSTOMER_ID = 'customer_id';
91
+
92
+ /** Add new payment method feature */
93
+ const FEATURE_ADD_PAYMENT_METHOD = 'add_payment_method';
94
+
95
+ /** Apple Pay feature */
96
+ const FEATURE_APPLE_PAY = 'apple_pay';
97
+
98
+ /** Admin token editor feature */
99
+ const FEATURE_TOKEN_EDITOR = 'token_editor';
100
+
101
+ /** Subscriptions integration ID */
102
+ const INTEGRATION_SUBSCRIPTIONS = 'subscriptions';
103
+
104
+ /** Pre-orders integration ID */
105
+ const INTEGRATION_PRE_ORDERS = 'pre_orders';
106
+
107
+ /** @var Payment_Gateway_Plugin the parent plugin class */
108
+ private $plugin;
109
+
110
+ /** @var string payment type, one of 'credit-card' */
111
+ private $payment_type;
112
+
113
+ /** @var array associative array of environment id to display name, defaults to 'production' => 'Production' */
114
+ private $environments;
115
+
116
+ /** @var array associative array of card type to display name */
117
+ private $available_card_types;
118
+
119
+ /** @var array optional array of currency codes this gateway is allowed for */
120
+ protected $currencies;
121
+
122
+ /** @var string configuration option: the transaction environment, one of $this->environments keys */
123
+ private $environment;
124
+
125
+ /** @var string configuration option: the type of transaction, whether purchase or authorization, defaults to 'charge' */
126
+ private $transaction_type;
127
+
128
+ /** @var string configuration option: whether transactions should always be charged if the order is virtual-only, defaults to 'no' */
129
+ private $charge_virtual_orders;
130
+
131
+ /** @var string configuration option: whether orders can be partially captured multiple times */
132
+ private $enable_partial_capture;
133
+
134
+ /** @var string configuration option: whether orders are captured when switched to a "paid" status */
135
+ private $enable_paid_capture;
136
+
137
+ /** @var array configuration option: card types to show images for */
138
+ private $card_types;
139
+
140
+ /** @var string configuration option: indicates whether a Card Security Code field will be presented on checkout, either 'yes' or 'no' */
141
+ private $enable_csc;
142
+
143
+ /** @var string configuration option: indicates whether a Card Security Code field will be presented for saved cards at checkout, either 'yes' or 'no' */
144
+ private $enable_token_csc;
145
+
146
+ /** @var string configuration option: indicates whether tokenization is enabled, either 'yes' or 'no' */
147
+ private $tokenization;
148
+
149
+ /** @var string configuration option: indicates whether detailed customer decline messages should be displayed at checkout, either 'yes' or 'no' */
150
+ private $enable_customer_decline_messages;
151
+
152
+ /** @var string configuration option: 4 options for debug mode - off, checkout, log, both */
153
+ private $debug_mode;
154
+
155
+ /** @var string configuration option: whether to use a sibling gateway's connection/authentication settings */
156
+ private $inherit_settings;
157
+
158
+ /** @var array of shared setting names, if any. */
159
+ private $shared_settings = array();
160
+
161
+ /** @var Payment_Gateway_Payment_Tokens_Handler payment tokens handler instance */
162
+ protected $payment_tokens_handler;
163
+
164
+ /** @var Payment_Gateway\Handlers\Capture capture handler instance */
165
+ protected $capture_handler;
166
+
167
+ /** @var array of Payment_Gateway_Integration objects for Subscriptions, Pre-Orders, etc. */
168
+ protected $integrations;
169
+
170
+
171
+ /**
172
+ * Initialize the gateway
173
+ *
174
+ * Args:
175
+ *
176
+ * + `method_title` - string admin method title, ie 'Intuit QBMS', defaults to 'Settings'
177
+ * + `method_description` - string admin method description, defaults to ''
178
+ * + `supports` - array list of supported gateway features, possible values include:
179
+ * 'products', 'card_types', 'tokenziation', 'charge', 'authorization', 'subscriptions',
180
+ * 'subscription_suspension', 'subscription_cancellation', 'subscription_reactivation',
181
+ * 'subscription_amount_changes', 'subscription_date_changes', 'subscription_payment_method_change',
182
+ * 'customer_decline_messages'
183
+ * Defaults to 'products', 'charge' (credit-card gateways only)
184
+ * + `payment_type` - 'credit-card'
185
+ * + `card_types` - array associative array of card type to display name, used if the payment_type is 'credit-card' and the 'card_types' feature is supported. Defaults to:
186
+ * 'VISA' => 'Visa', 'MC' => 'MasterCard', 'AMEX' => 'American Express', 'DISC' => 'Discover', 'DINERS' => 'Diners', 'JCB' => 'JCB'
187
+ * + `environments` - associative array of environment id to display name, merged with default of 'production' => 'Production'
188
+ * + `currencies` - array of currency codes this gateway is allowed for, defaults to plugin accepted currencies
189
+ * + `countries` - array of two-letter country codes this gateway is allowed for, defaults to all
190
+ * + `shared_settings` - array of shared setting names, if any.
191
+ *
192
+ * @since 3.0.0
193
+ * @param string $id the gateway id
194
+ * @param Payment_Gateway_Plugin $plugin the parent plugin class
195
+ * @param array $args gateway arguments
196
+ */
197
+ public function __construct( $id, $plugin, $args ) {
198
+
199
+ // first setup the gateway and payment type for this gateway
200
+ $this->payment_type = isset( $args['payment_type'] ) ? $args['payment_type'] : self::PAYMENT_TYPE_CREDIT_CARD;
201
+
202
+ // default credit card gateways to supporting 'charge' transaction type, this could be overridden by the 'supports' constructor parameter to include (or only support) authorization
203
+ if ( $this->is_credit_card_gateway() ) {
204
+ $this->add_support( self::FEATURE_CREDIT_CARD_CHARGE );
205
+ }
206
+
207
+ // required fields
208
+ $this->id = $id; // @see WC_Payment_Gateway::$id
209
+
210
+ $this->plugin = $plugin;
211
+ // kind of sucks, but we need to register back to the plugin because
212
+ // there's no other way of grabbing existing gateways so as to avoid
213
+ // double-instantiation errors (esp for shared settings)
214
+ $this->get_plugin()->set_gateway( $id, $this );
215
+
216
+ // optional parameters
217
+ if ( isset( $args['method_title'] ) ) {
218
+ $this->method_title = $args['method_title']; // @see WC_Settings_API::$method_title
219
+ }
220
+ if ( isset( $args['method_description'] ) ) {
221
+ $this->method_description = $args['method_description']; // @see WC_Settings_API::$method_description
222
+ }
223
+ if ( isset( $args['supports'] ) ) {
224
+ $this->set_supports( $args['supports'] );
225
+ }
226
+ if ( isset( $args['card_types'] ) ) {
227
+ $this->available_card_types = $args['card_types'];
228
+ }
229
+ if ( isset( $args['environments'] ) ) {
230
+ $this->environments = array_merge( $this->get_environments(), $args['environments'] );
231
+ }
232
+ if ( isset( $args['countries'] ) ) {
233
+ $this->countries = $args['countries']; // @see WC_Payment_Gateway::$countries
234
+ }
235
+ if ( isset( $args['shared_settings'] ) ) {
236
+ $this->shared_settings = $args['shared_settings'];
237
+ }
238
+ if ( isset( $args['currencies'] ) ) {
239
+ $this->currencies = $args['currencies'];
240
+ } else {
241
+ $this->currencies = $this->get_plugin()->get_accepted_currencies();
242
+ }
243
+ if ( isset( $args['order_button_text'] ) ) {
244
+ $this->order_button_text = $args['order_button_text'];
245
+ } else {
246
+ $this->order_button_text = $this->get_order_button_text();
247
+ }
248
+
249
+ // always want to render the field area, even for gateways with no fields, so we can display messages @see WC_Payment_Gateway::$has_fields
250
+ $this->has_fields = true;
251
+
252
+ // default icon filter @see WC_Payment_Gateway::$icon
253
+ $this->icon = apply_filters( 'wc_' . $this->get_id() . '_icon', '' );
254
+
255
+ // Load the form fields
256
+ $this->init_form_fields();
257
+
258
+ // initialize and load the settings
259
+ $this->init_settings();
260
+
261
+ $this->load_settings();
262
+
263
+ $this->init_payment_tokens_handler();
264
+
265
+ $this->init_integrations();
266
+
267
+ // initialize the capture handler
268
+ $this->init_capture_handler();
269
+
270
+ // pay page fallback
271
+ $this->add_pay_page_handler();
272
+
273
+ // filter order received text for held orders
274
+ add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'maybe_render_held_order_received_text' ), 10, 2 );
275
+
276
+ // admin only
277
+ if ( is_admin() ) {
278
+
279
+ // save settings
280
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->get_id(), array( $this, 'process_admin_options' ) );
281
+ }
282
+
283
+ // Enqueue the necessary scripts & styles
284
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
285
+
286
+ // add API request logging
287
+ $this->add_api_request_logging();
288
+
289
+ // add milestone action hooks
290
+ $this->add_milestone_hooks();
291
+ }
292
+
293
+
294
+ /**
295
+ * Adds the various milestone hooks like "payment processed".
296
+ *
297
+ * @since 3.0.0
298
+ */
299
+ protected function add_milestone_hooks() {
300
+
301
+ $plugin = $this->get_plugin();
302
+
303
+ // first successful payment
304
+ add_action( 'wc_payment_gateway_' . $this->get_id() . '_payment_processed', function( $order ) use ( &$plugin ) {
305
+ $plugin->get_lifecycle_handler()->trigger_milestone( 'payment-processed', __( 'you successfully processed a payment!', 'woocommerce-square' ) );
306
+ } );
307
+
308
+ // first successful refund
309
+ add_action( 'wc_payment_gateway_' . $this->get_id() . '_refund_processed', function( $order ) use ( &$plugin ) {
310
+ $plugin->get_lifecycle_handler()->trigger_milestone( 'refund-processed', __( 'you successfully processed a refund!', 'woocommerce-square' ) );
311
+ } );
312
+ }
313
+
314
+
315
+ /**
316
+ * Loads the plugin configuration settings
317
+ *
318
+ * @since 3.0.0
319
+ */
320
+ public function load_settings() {
321
+
322
+ // define user set variables
323
+ foreach ( $this->settings as $setting_key => $setting ) {
324
+ $this->$setting_key = $setting;
325
+ }
326
+
327
+ // inherit settings from sibling gateway(s)
328
+ if ( $this->inherit_settings() ) {
329
+ $this->load_shared_settings();
330
+ }
331
+ }
332
+
333
+
334
+ /**
335
+ * Loads any shared settings from sibling gateways.
336
+ *
337
+ * @since 3.0.0
338
+ */
339
+ protected function load_shared_settings() {
340
+
341
+ // get any other sibling gateways
342
+ $other_gateway_ids = array_diff( $this->get_plugin()->get_gateway_ids(), array( $this->get_id() ) );
343
+
344
+ // determine if any sibling gateways have any configured shared settings
345
+ foreach ( $other_gateway_ids as $other_gateway_id ) {
346
+
347
+ $other_gateway_settings = $this->get_plugin()->get_gateway_settings( $other_gateway_id );
348
+
349
+ // if the other gateway isn't also trying to inherit settings...
350
+ if ( ! isset( $other_gateway_settings['inherit_settings'] ) || 'no' === $other_gateway_settings['inherit_settings'] ) {
351
+
352
+ // load the other gateway so we can access the shared settings properly
353
+ $other_gateway = $this->get_plugin()->get_gateway( $other_gateway_id );
354
+
355
+ // skip this gateway if it isn't meant to share its settings
356
+ if ( ! $other_gateway->share_settings() ) {
357
+ continue;
358
+ }
359
+
360
+ foreach ( $this->shared_settings as $setting_key ) {
361
+ $this->$setting_key = $other_gateway->$setting_key;
362
+ }
363
+ }
364
+ }
365
+ }
366
+
367
+
368
+ /**
369
+ * Enqueue the necessary scripts & styles for the gateway, including the
370
+ * payment form assets (if supported) and any gateway-specific assets.
371
+ *
372
+ * @since 3.0.0
373
+ */
374
+ public function enqueue_scripts() {
375
+
376
+ if ( ! $this->is_available() ) {
377
+ return;
378
+ }
379
+
380
+ // payment form assets
381
+ if ( $this->supports_payment_form() ) {
382
+
383
+ $this->enqueue_payment_form_assets();
384
+ }
385
+
386
+ // gateway-specific assets
387
+ $this->enqueue_gateway_assets();
388
+ }
389
+
390
+
391
+ /**
392
+ * Enqueue the payment form JS, CSS, and localized
393
+ * JS params
394
+ *
395
+ * @since 3.0.0
396
+ */
397
+ protected function enqueue_payment_form_assets() {
398
+
399
+ // bail if on my account page and *not* on add payment method page
400
+ if ( is_account_page() && ! is_add_payment_method_page() ) {
401
+ return;
402
+ }
403
+
404
+ $handle = 'wc-square-payment-gateway-payment-form';
405
+
406
+ // Frontend JS
407
+ wp_enqueue_script( $handle, $this->get_plugin()->get_plugin_url() . '/assets/js/frontend/' . $handle . '.min.js', array( 'jquery-payment' ), Plugin::VERSION, true );
408
+
409
+ // Frontend CSS
410
+ wp_enqueue_style( $handle, $this->get_plugin()->get_plugin_url() . '/assets/css/frontend/' . $handle . '.min.css', array(), Plugin::VERSION );
411
+
412
+ // localized JS params
413
+ $this->localize_script( $handle, $this->get_payment_form_js_localized_script_params() );
414
+ }
415
+
416
+
417
+ /**
418
+ * Returns an array of JS script params to localize for the
419
+ * payment form JS. Generally used for i18n purposes.
420
+ *
421
+ * @since 3.0.0
422
+ * @return array associative array of param name to value
423
+ */
424
+ protected function get_payment_form_js_localized_script_params() {
425
+
426
+ /**
427
+ * Payment Form JS Localized Script Params Filter.
428
+ *
429
+ * Allow actors to modify the JS localized script params for the
430
+ * payment form.
431
+ *
432
+ * @since 3.0.0
433
+ * @param array $params
434
+ * @return array
435
+ */
436
+ return apply_filters( 'sv_wc_payment_gateway_payment_form_js_localized_script_params', array(
437
+ 'card_number_missing' => esc_html__( 'Card number is missing', 'woocommerce-square' ),
438
+ 'card_number_invalid' => esc_html__( 'Card number is invalid', 'woocommerce-square' ),
439
+ 'card_number_digits_invalid' => esc_html__( 'Card number is invalid (only digits allowed)', 'woocommerce-square' ),
440
+ 'card_number_length_invalid' => esc_html__( 'Card number is invalid (wrong length)', 'woocommerce-square' ),
441
+ 'cvv_missing' => esc_html__( 'Card security code is missing', 'woocommerce-square' ),
442
+ 'cvv_digits_invalid' => esc_html__( 'Card security code is invalid (only digits are allowed)', 'woocommerce-square' ),
443
+ 'cvv_length_invalid' => esc_html__( 'Card security code is invalid (must be 3 or 4 digits)', 'woocommerce-square' ),
444
+ 'card_exp_date_invalid' => esc_html__( 'Card expiration date is invalid', 'woocommerce-square' ),
445
+ 'check_number_digits_invalid' => esc_html__( 'Check Number is invalid (only digits are allowed)', 'woocommerce-square' ),
446
+ 'check_number_missing' => esc_html__( 'Check Number is missing', 'woocommerce-square' ),
447
+ 'drivers_license_state_missing' => esc_html__( 'Drivers license state is missing', 'woocommerce-square' ),
448
+ 'drivers_license_number_missing' => esc_html__( 'Drivers license number is missing', 'woocommerce-square' ),
449
+ 'drivers_license_number_invalid' => esc_html__( 'Drivers license number is invalid', 'woocommerce-square' ),
450
+ 'account_number_missing' => esc_html__( 'Account Number is missing', 'woocommerce-square' ),
451
+ 'account_number_invalid' => esc_html__( 'Account Number is invalid (only digits are allowed)', 'woocommerce-square' ),
452
+ 'account_number_length_invalid' => esc_html__( 'Account number is invalid (must be between 5 and 17 digits)', 'woocommerce-square' ),
453
+ 'routing_number_missing' => esc_html__( 'Routing Number is missing', 'woocommerce-square' ),
454
+ 'routing_number_digits_invalid' => esc_html__( 'Routing Number is invalid (only digits are allowed)', 'woocommerce-square' ),
455
+ 'routing_number_length_invalid' => esc_html__( 'Routing number is invalid (must be 9 digits)', 'woocommerce-square' ),
456
+ ) );
457
+ }
458
+
459
+
460
+ /**
461
+ * Enqueue the gateway-specific assets if present, including JS, CSS, and
462
+ * localized script params
463
+ *
464
+ * @since 3.0.0
465
+ */
466
+ protected function enqueue_gateway_assets() {
467
+
468
+ $handle = $this->get_gateway_js_handle();
469
+ $js_path = $this->get_plugin()->get_plugin_path() . '/assets/js/frontend/' . $handle . '.min.js';
470
+ $css_path = $this->get_plugin()->get_plugin_path() . '/assets/css/frontend/' . $handle . '.min.css';
471
+
472
+ // JS
473
+ if ( is_readable( $js_path ) ) {
474
+
475
+ $js_url = $this->get_plugin()->get_plugin_url() . '/assets/js/frontend/' . $handle . '.min.js';
476
+
477
+ /**
478
+ * Concrete Payment Gateway JS URL
479
+ *
480
+ * Allow actors to modify the URL used when loading a concrete
481
+ * payment gateway's javascript.
482
+ *
483
+ * @since 3.0.0
484
+ * @param string $js_url JS asset URL
485
+ * @return string
486
+ */
487
+ $js_url = apply_filters( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_javascript_url', $js_url );
488
+
489
+ wp_enqueue_script( $handle, $js_url, array(), $this->get_plugin()->get_version(), true );
490
+ }
491
+
492
+ // CSS
493
+ if ( is_readable( $css_path ) ) {
494
+
495
+ $css_url = $this->get_plugin()->get_plugin_url() . '/assets/css/frontend/' . $handle . '.min.css';
496
+
497
+ /**
498
+ * Concrete Payment Gateway CSS URL
499
+ *
500
+ * Allow actors to modify the URL used when loading a concrete payment
501
+ * gateway's CSS.
502
+ *
503
+ * @since 3.0.0
504
+ * @param string $css_url CSS asset URL
505
+ * @return string
506
+ */
507
+ $css_url = apply_filters( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_css_url', $css_url );
508
+
509
+ wp_enqueue_style( $handle, $css_url, array(), $this->get_plugin()->get_version() );
510
+ }
511
+ }
512
+
513
+
514
+ /**
515
+ * Return the gateway-specifics JS script handle. This is used for:
516
+ *
517
+ * + enqueuing the script
518
+ * + the localized JS script param object name
519
+ *
520
+ * Defaults to 'wc-<plugin ID dasherized>'.
521
+ *
522
+ * @since 3.0.0
523
+ * @return string
524
+ */
525
+ protected function get_gateway_js_handle() {
526
+
527
+ return 'wc-' . $this->get_plugin()->get_id_dasherized();
528
+ }
529
+
530
+ /**
531
+ * Localize a script once. Gateway plugins that have multiple gateways should
532
+ * only have their params localized once.
533
+ *
534
+ * @since 3.0.0
535
+ * @param string $handle script handle to localize
536
+ * @param array $params script params to localize
537
+ */
538
+ protected function localize_script( $handle, $params ) {
539
+
540
+ // If the script isn't loaded, bail
541
+ if ( ! wp_script_is( $handle, 'enqueued' ) ) {
542
+ return;
543
+ }
544
+
545
+ global $wp_scripts;
546
+
547
+ $object_name = str_replace( '-', '_', $handle ) . '_params';
548
+
549
+ // If the plugin's JS params already exists in the localized data, bail
550
+ if ( $wp_scripts instanceof \WP_Scripts && strpos( $wp_scripts->get_data( $handle, 'data' ), $object_name ) ) {
551
+ return;
552
+ }
553
+
554
+ wp_localize_script( $handle, $object_name, $params );
555
+ }
556
+
557
+
558
+ /**
559
+ * Returns true if on the pay page and this is the currently selected gateway
560
+ *
561
+ * @since 3.0.0
562
+ *
563
+ * @return null|bool true if on pay page and is currently selected gateways, false if on pay page and not the selected gateway, null otherwise
564
+ */
565
+ public function is_pay_page_gateway() {
566
+
567
+ if ( is_checkout_pay_page() ) {
568
+
569
+ $order_id = $this->get_checkout_pay_page_order_id();
570
+
571
+ if ( $order_id ) {
572
+ $order = wc_get_order( $order_id );
573
+
574
+ return Order_Compatibility::get_prop( $order, 'payment_method' ) === $this->get_id();
575
+ }
576
+
577
+ }
578
+
579
+ return null;
580
+ }
581
+
582
+
583
+ /**
584
+ * Gets the order button text:
585
+ *
586
+ * Direct gateway: "Place order"
587
+ * Redirect/Hosted gateway: "Continue"
588
+ *
589
+ * @since 3.0.0
590
+ */
591
+ protected function get_order_button_text() {
592
+
593
+ $text = $this->is_hosted_gateway() ? esc_html__( 'Continue', 'woocommerce-square' ) : esc_html__( 'Place order', 'woocommerce-square' );
594
+
595
+ /**
596
+ * Payment Gateway Place Order Button Text Filter.
597
+ *
598
+ * Allow actors to modify the "place order" button text.
599
+ *
600
+ * @since 3.0.0
601
+ * @param string $text button text
602
+ * @param Payment_Gateway $this instance
603
+ */
604
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_order_button_text', $text, $this );
605
+ }
606
+
607
+
608
+ /**
609
+ * Adds a default simple pay page handler
610
+ *
611
+ * @since 3.0.0
612
+ */
613
+ protected function add_pay_page_handler() {
614
+ add_action( 'woocommerce_receipt_' . $this->get_id(), array( $this, 'payment_page' ) );
615
+ }
616
+
617
+
618
+ /**
619
+ * Render a simple payment page
620
+ *
621
+ * @since 3.0.0
622
+ * @param int $order_id identifies the order
623
+ */
624
+ public function payment_page( $order_id ) {
625
+ echo '<p>' . esc_html__( 'Thank you for your order.', 'woocommerce-square' ) . '</p>';
626
+ }
627
+
628
+
629
+ /** Payment Form Feature **************************************************/
630
+
631
+
632
+ /**
633
+ * Returns true if the gateway supports the payment form feature
634
+ *
635
+ * @since 3.0.0
636
+ * @return bool
637
+ */
638
+ public function supports_payment_form() {
639
+
640
+ return $this->supports( self::FEATURE_PAYMENT_FORM );
641
+ }
642
+
643
+
644
+ /**
645
+ * Render the payment fields
646
+ *
647
+ * @since 3.0.0
648
+ * @see WC_Payment_Gateway::payment_fields()
649
+ * @see Payment_Gateway_Payment_Form class
650
+ */
651
+ public function payment_fields() {
652
+
653
+ if ( $this->supports_payment_form() ) {
654
+
655
+ $this->get_payment_form_instance()->render();
656
+
657
+ } else {
658
+
659
+ parent::payment_fields();
660
+ }
661
+ }
662
+
663
+
664
+ /**
665
+ * Gets the payment form class instance.
666
+ *
667
+ * @since 3.0.0
668
+ *
669
+ * @return Payment_Gateway_Payment_Form
670
+ */
671
+ public function get_payment_form_instance() {
672
+
673
+ return new Payment_Gateway_Payment_Form( $this );
674
+ }
675
+
676
+
677
+ /**
678
+ * Get the payment form field defaults, primarily for gateways to override
679
+ * and set dummy credit card info when in the test environment
680
+ *
681
+ * @since 3.0.0
682
+ * @return array
683
+ */
684
+ public function get_payment_method_defaults() {
685
+
686
+ assert( $this->supports_payment_form() );
687
+
688
+ $defaults = array(
689
+ 'account-number' => '',
690
+ 'routing-number' => '',
691
+ 'expiry' => '',
692
+ 'csc' => '',
693
+ );
694
+
695
+ if ( $this->is_test_environment() ) {
696
+ $defaults['expiry'] = '01/' . ( date( 'y' ) + 1 );
697
+ $defaults['csc'] = '123';
698
+ }
699
+
700
+ return $defaults;
701
+ }
702
+
703
+
704
+ /** Tokenization **************************************************/
705
+
706
+
707
+ /**
708
+ * Initialize payment tokens handler.
709
+ *
710
+ * @since 3.0.0
711
+ */
712
+ protected function init_payment_tokens_handler() {
713
+
714
+ $this->payment_tokens_handler = $this->build_payment_tokens_handler();
715
+ }
716
+
717
+
718
+ /**
719
+ * Gets the payment tokens handler instance.
720
+ *
721
+ * Concrete classes can override this method to return a custom implementation.
722
+ *
723
+ * @since 3.0.0
724
+ *
725
+ * @return Payment_Gateway_Payment_Tokens_Handler
726
+ */
727
+ protected function build_payment_tokens_handler() {
728
+ return new Payment_Gateway_Payment_Tokens_Handler( $this );
729
+ }
730
+
731
+
732
+ /**
733
+ * Gets the payment tokens handler instance.
734
+ *
735
+ * @since 3.0.0
736
+ *
737
+ * @return Payment_Gateway_Payment_Tokens_Handler
738
+ */
739
+ public function get_payment_tokens_handler() {
740
+
741
+ return $this->payment_tokens_handler;
742
+ }
743
+
744
+
745
+ /**
746
+ * Determines if tokenization takes place prior to transaction processing.
747
+ *
748
+ * @since 3.0.0
749
+ *
750
+ * @return bool
751
+ */
752
+ public function tokenize_before_sale() {
753
+ return false;
754
+ }
755
+
756
+
757
+ /**
758
+ * Determines tokenization takes place during a transaction request.
759
+ *
760
+ * @since 3.0.0
761
+ *
762
+ * @return bool
763
+ */
764
+ public function tokenize_with_sale() {
765
+ return false;
766
+ }
767
+
768
+
769
+ /**
770
+ * Determines tokenization takes place after a transaction request.
771
+ *
772
+ * @since 3.0.0
773
+ *
774
+ * @return bool
775
+ */
776
+ public function tokenize_after_sale() {
777
+ return false;
778
+ }
779
+
780
+
781
+ /**
782
+ * Determines if the gateway supports the admin token editor feature.
783
+ *
784
+ * @since 3.0.0
785
+ *
786
+ * @return bool
787
+ */
788
+ public function supports_token_editor() {
789
+ return $this->supports( self::FEATURE_TOKEN_EDITOR );
790
+ }
791
+
792
+
793
+ /** Integrations Feature **************************************************/
794
+
795
+
796
+ /**
797
+ * Initializes supported integrations.
798
+ *
799
+ * @since 3.0.0
800
+ */
801
+ public function init_integrations() {
802
+
803
+ if ( $this->supports_subscriptions() ) {
804
+ $this->integrations[ self::INTEGRATION_SUBSCRIPTIONS ] = $this->build_subscriptions_integration();
805
+ }
806
+
807
+ if ( $this->supports_pre_orders() ) {
808
+ $this->integrations[ self::INTEGRATION_PRE_ORDERS ] = $this->build_pre_orders_integration();
809
+ }
810
+
811
+ /**
812
+ * Payment Gateway Integrations Initialized Action.
813
+ *
814
+ * Fired when integrations (Subscriptons/Pre-Orders) have been loaded and
815
+ * initialized.
816
+ *
817
+ * @since 3.0.0
818
+ *
819
+ * @param Payment_Gateway_Direct $this instance
820
+ */
821
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_init_integrations', $this );
822
+ }
823
+
824
+
825
+ /**
826
+ * Gets an array of available integration objects
827
+ *
828
+ * @since 3.0.0
829
+ * @return array
830
+ */
831
+ public function get_integrations() {
832
+
833
+ return $this->integrations;
834
+ }
835
+
836
+
837
+ /**
838
+ * Gets the integration object for the given ID.
839
+ *
840
+ * @since 3.0.0
841
+ *
842
+ * @param string $id the integration ID, e.g. subscriptions
843
+ * @return SquareFramework\PaymentGateway\Integrations\Payment_Gateway_Integration|null
844
+ */
845
+ public function get_integration( $id ) {
846
+
847
+ return isset( $this->integrations[ $id ] ) ? $this->integrations[ $id ] : null;
848
+ }
849
+
850
+
851
+ /**
852
+ * Builds the Subscriptions integration class instance.
853
+ *
854
+ * Concrete classes can override this method to return a custom implementation.
855
+ *
856
+ * @since 3.0.0
857
+ *
858
+ * @return Payment_Gateway_Integration_Subscriptions
859
+ */
860
+ protected function build_subscriptions_integration() {
861
+
862
+ return new Payment_Gateway_Integration_Subscriptions( $this );
863
+ }
864
+
865
+
866
+ /**
867
+ * Gets the Subscriptions integration class instance.
868
+ *
869
+ * @since 3.0.0
870
+ *
871
+ * @return Payment_Gateway_Integration_Subscriptions|null
872
+ */
873
+ public function get_subscriptions_integration() {
874
+
875
+ return isset( $this->integrations[ self::INTEGRATION_SUBSCRIPTIONS ] ) ? $this->integrations[ self::INTEGRATION_SUBSCRIPTIONS ] : null;
876
+ }
877
+
878
+
879
+ /**
880
+ * Builds the Pre-Orders integration class instance.
881
+ *
882
+ * Concrete classes can override this method to return a custom implementation.
883
+ *
884
+ * @since 3.0.0
885
+ *
886
+ * @return Payment_Gateway_Integration_Pre_Orders
887
+ */
888
+ protected function build_pre_orders_integration() {
889
+
890
+ return new Payment_Gateway_Integration_Pre_Orders( $this );
891
+ }
892
+
893
+
894
+ /**
895
+ * Gets the Pre-Orders integration class instance.
896
+ *
897
+ * @since 3.0.0
898
+ *
899
+ * @return Payment_Gateway_Integration_Pre_Orders|null
900
+ */
901
+ public function get_pre_orders_integration() {
902
+
903
+ return isset( $this->integrations[ self::INTEGRATION_PRE_ORDERS ] ) ? $this->integrations[ self::INTEGRATION_PRE_ORDERS ] : null;
904
+ }
905
+
906
+
907
+ /**
908
+ * Determines if the gateway supports Subscriptions.
909
+ *
910
+ * A gateway supports Subscriptions if all of the following are true:
911
+ *
912
+ * + Subscriptions is active
913
+ * + tokenization is supported
914
+ * + tokenization is enabled
915
+ *
916
+ * Concrete gateways can override this to conditionally support Subscriptions
917
+ * based on certain settings (e.g. only when CSC is not required, etc.)
918
+ *
919
+ * @since 3.0.0
920
+ *
921
+ * @return bool
922
+ */
923
+ public function supports_subscriptions() {
924
+
925
+ return $this->get_plugin()->is_subscriptions_active() && $this->supports_tokenization() && $this->tokenization_enabled();
926
+ }
927
+
928
+
929
+ /**
930
+ * Determines if the gateway supports Pre-Orders.
931
+ *
932
+ * A gateway supports Pre-Orders if all of the following are true:
933
+ *
934
+ * + Pre-Orders is active
935
+ * + tokenization is supported
936
+ * + tokenization is enabled
937
+ *
938
+ * Concrete gateways can override this to conditionally support Pre-Orders
939
+ * based on certain settings (e.g. only when CSC is not required, etc.)
940
+ *
941
+ * @since 3.0.0
942
+ *
943
+ * @return bool
944
+ */
945
+ public function supports_pre_orders() {
946
+
947
+ return $this->get_plugin()->is_pre_orders_active() && $this->supports_tokenization() && $this->tokenization_enabled();
948
+ }
949
+
950
+
951
+ /** Apple Pay Feature *****************************************************/
952
+
953
+
954
+ /**
955
+ * Determines whether this gateway supports Apple Pay.
956
+ *
957
+ * @since 3.0.0
958
+ *
959
+ * @return bool
960
+ */
961
+ public function supports_apple_pay() {
962
+
963
+ return $this->supports( self::FEATURE_APPLE_PAY );
964
+ }
965
+
966
+
967
+ /**
968
+ * Gets the Apple Pay gateway capabilities.
969
+ *
970
+ * Gateways should override this if they have more or less capabilities than
971
+ * the default. See https://developer.apple.com/reference/applepayjs/paymentrequest/1916123-merchantcapabilities
972
+ * for valid values.
973
+ *
974
+ * @since 3.0.0
975
+ *
976
+ * @return array
977
+ */
978
+ public function get_apple_pay_capabilities() {
979
+
980
+ return array(
981
+ 'supports3DS',
982
+ 'supportsCredit',
983
+ 'supportsDebit',
984
+ );
985
+ }
986
+
987
+
988
+ /**
989
+ * Gets the currencies supported by Apple Pay.
990
+ *
991
+ * @since 3.0.0
992
+ *
993
+ * @return array
994
+ */
995
+ public function get_apple_pay_currencies() {
996
+
997
+ return array( 'USD' );
998
+ }
999
+
1000
+
1001
+ /**
1002
+ * Adds the Apple Pay payment data to the order object.
1003
+ *
1004
+ * Gateways should override this to set the appropriate values depending on
1005
+ * how their processing API needs to handle the data.
1006
+ *
1007
+ * @since 3.0.0
1008
+ *
1009
+ * @param \WC_Order the order object
1010
+ * @param Payment_Gateway_Apple_Pay_Payment_Response authorized payment response
1011
+ * @return \WC_Order
1012
+ */
1013
+ public function get_order_for_apple_pay( \WC_Order $order, Payment_Gateway_Apple_Pay_Payment_Response $response ) {
1014
+
1015
+ $order->payment->account_number = $response->get_last_four();
1016
+ $order->payment->last_four = $response->get_last_four();
1017
+ $order->payment->card_type = $response->get_card_type();
1018
+
1019
+ return $order;
1020
+ }
1021
+
1022
+
1023
+ /**
1024
+ * Get the default payment method title, which is configurable within the
1025
+ * admin and displayed on checkout
1026
+ *
1027
+ * @since 3.0.0
1028
+ * @return string payment method title to show on checkout
1029
+ */
1030
+ protected function get_default_title() {
1031
+
1032
+ // defaults for credit card, override for others
1033
+ if ( $this->is_credit_card_gateway() ) {
1034
+ return esc_html__( 'Credit Card', 'woocommerce-square' );
1035
+ }
1036
+
1037
+ return '';
1038
+ }
1039
+
1040
+
1041
+ /**
1042
+ * Get the default payment method description, which is configurable
1043
+ * within the admin and displayed on checkout
1044
+ *
1045
+ * @since 3.0.0
1046
+ * @return string payment method description to show on checkout
1047
+ */
1048
+ protected function get_default_description() {
1049
+
1050
+ // defaults for credit card, override for others
1051
+ if ( $this->is_credit_card_gateway() ) {
1052
+ return esc_html__( 'Pay securely using your credit card.', 'woocommerce-square' );
1053
+ }
1054
+
1055
+ return '';
1056
+ }
1057
+
1058
+
1059
+ /**
1060
+ * Initialize payment gateway settings fields
1061
+ *
1062
+ * @since 3.0.0
1063
+ * @see WC_Settings_API::init_form_fields()
1064
+ */
1065
+ public function init_form_fields() {
1066
+
1067
+ // common top form fields
1068
+ $this->form_fields = array(
1069
+
1070
+ 'enabled' => array(
1071
+ 'title' => esc_html__( 'Enable / Disable', 'woocommerce-square' ),
1072
+ 'label' => esc_html__( 'Enable this gateway', 'woocommerce-square' ),
1073
+ 'type' => 'checkbox',
1074
+ 'default' => 'no',
1075
+ ),
1076
+
1077
+ 'title' => array(
1078
+ 'title' => esc_html__( 'Title', 'woocommerce-square' ),
1079
+ 'type' => 'text',
1080
+ 'desc_tip' => esc_html__( 'Payment method title that the customer will see during checkout.', 'woocommerce-square' ),
1081
+ 'default' => $this->get_default_title(),
1082
+ ),
1083
+
1084
+ 'description' => array(
1085
+ 'title' => esc_html__( 'Description', 'woocommerce-square' ),
1086
+ 'type' => 'textarea',
1087
+ 'desc_tip' => esc_html__( 'Payment method description that the customer will see during checkout.', 'woocommerce-square' ),
1088
+ 'default' => $this->get_default_description(),
1089
+ ),
1090
+
1091
+ );
1092
+
1093
+ // Card Security Code (CVV) field
1094
+ if ( $this->is_credit_card_gateway() ) {
1095
+ $this->form_fields = $this->add_csc_form_fields( $this->form_fields );
1096
+ }
1097
+
1098
+ // both credit card authorization & charge supported
1099
+ if ( $this->supports_credit_card_authorization() && $this->supports_credit_card_charge() ) {
1100
+ $this->form_fields = $this->add_authorization_charge_form_fields( $this->form_fields );
1101
+ }
1102
+
1103
+ // card types support
1104
+ if ( $this->supports_card_types() ) {
1105
+ $this->form_fields = $this->add_card_types_form_fields( $this->form_fields );
1106
+ }
1107
+
1108
+ // tokenization support
1109
+ if ( $this->supports_tokenization() ) {
1110
+ $this->form_fields = $this->add_tokenization_form_fields( $this->form_fields );
1111
+ }
1112
+
1113
+ // add "detailed customer decline messages" option if the feature is supported
1114
+ if ( $this->supports( self::FEATURE_DETAILED_CUSTOMER_DECLINE_MESSAGES ) ) {
1115
+ $this->form_fields['enable_customer_decline_messages'] = array(
1116
+ 'title' => esc_html__( 'Detailed Decline Messages', 'woocommerce-square' ),
1117
+ 'type' => 'checkbox',
1118
+ 'label' => esc_html__( 'Check to enable detailed decline messages to the customer during checkout when possible, rather than a generic decline message.', 'woocommerce-square' ),
1119
+ 'default' => 'no',
1120
+ );
1121
+ }
1122
+
1123
+ // debug mode
1124
+ $this->form_fields['debug_mode'] = array(
1125
+ 'title' => esc_html__( 'Debug Mode', 'woocommerce-square' ),
1126
+ 'type' => 'select',
1127
+ /* translators: Placeholders: %1$s - <a> tag, %2$s - </a> tag */
1128
+ 'desc' => sprintf( esc_html__( 'Show Detailed Error Messages and API requests/responses on the checkout page and/or save them to the %1$sdebug log%2$s', 'woocommerce-square' ), '<a href="' . Square_Helper::get_wc_log_file_url( $this->get_id() ) . '">', '</a>' ),
1129
+ 'default' => self::DEBUG_MODE_OFF,
1130
+ 'options' => array(
1131
+ self::DEBUG_MODE_OFF => esc_html__( 'Off', 'woocommerce-square' ),
1132
+ self::DEBUG_MODE_CHECKOUT => esc_html__( 'Show on Checkout Page', 'woocommerce-square' ),
1133
+ self::DEBUG_MODE_LOG => esc_html__( 'Save to Log', 'woocommerce-square' ),
1134
+ /* translators: show debugging information on both checkout page and in the log */
1135
+ self::DEBUG_MODE_BOTH => esc_html__( 'Both', 'woocommerce-square' )
1136
+ ),
1137
+ );
1138
+
1139
+ // if there is more than just the production environment available
1140
+ if ( count( $this->get_environments() ) > 1 ) {
1141
+ $this->form_fields = $this->add_environment_form_fields( $this->form_fields );
1142
+ }
1143
+
1144
+ // add the "inherit settings" toggle if there are settings shared with a sibling gateway
1145
+ if ( count( $this->shared_settings ) ) {
1146
+ $this->form_fields = $this->add_shared_settings_form_fields( $this->form_fields );
1147
+ }
1148
+
1149
+ // add unique method fields added by concrete gateway class
1150
+ $gateway_form_fields = $this->get_method_form_fields();
1151
+ $this->form_fields = array_merge( $this->form_fields, $gateway_form_fields );
1152
+
1153
+ // add the special 'shared-settings-field' class name to any shared settings fields
1154
+ foreach ( $this->shared_settings as $field_name ) {
1155
+ $this->form_fields[ $field_name ]['class'] = trim( isset( $this->form_fields[ $field_name ]['class'] ) ? $this->form_fields[ $field_name ]['class'] : '' ) . ' shared-settings-field';
1156
+ }
1157
+
1158
+ /**
1159
+ * Payment Gateway Form Fields Filter.
1160
+ *
1161
+ * Actors can use this to add, remove, or tweak gateway form fields
1162
+ *
1163
+ * @since 3.0.0
1164
+ * @param array $form_fields array of form fields in format required by WC_Settings_API
1165
+ * @param Payment_Gateway $this gateway instance
1166
+ */
1167
+ $this->form_fields = apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_form_fields', $this->form_fields, $this );
1168
+ }
1169
+
1170
+
1171
+ /**
1172
+ * Returns an array of form fields specific for this method.
1173
+ *
1174
+ * To add environment-dependent fields, include the 'class' form field argument
1175
+ * with 'environment-field production-field' where "production" matches a
1176
+ * key from the environments member
1177
+ *
1178
+ * @since 3.0.0
1179
+ * @return array of form fields
1180
+ */
1181
+ abstract protected function get_method_form_fields();
1182
+
1183
+
1184
+ /**
1185
+ * Adds the gateway environment form fields
1186
+ *
1187
+ * @since 3.0.0
1188
+ * @param array $form_fields gateway form fields
1189
+ * @return array $form_fields gateway form fields
1190
+ */
1191
+ protected function add_environment_form_fields( $form_fields ) {
1192
+
1193
+ $form_fields['environment'] = array(
1194
+ /* translators: environment as in a software environment (test/production) */
1195
+ 'title' => esc_html__( 'Environment', 'woocommerce-square' ),
1196
+ 'type' => 'select',
1197
+ 'default' => key( $this->get_environments() ), // default to first defined environment
1198
+ 'desc_tip' => esc_html__( 'Select the gateway environment to use for transactions.', 'woocommerce-square' ),
1199
+ 'options' => $this->get_environments(),
1200
+ );
1201
+
1202
+ return $form_fields;
1203
+ }
1204
+
1205
+
1206
+ /**
1207
+ * Adds the optional shared settings toggle element. The 'shared_settings'
1208
+ * optional constructor parameter must have been used in order for shared
1209
+ * settings to be supported.
1210
+ *
1211
+ * @since 3.0.0
1212
+ * @see Payment_Gateway::$shared_settings
1213
+ * @see Payment_Gateway::$inherit_settings
1214
+ * @param array $form_fields gateway form fields
1215
+ * @return array $form_fields gateway form fields
1216
+ */
1217
+ protected function add_shared_settings_form_fields( $form_fields ) {
1218
+
1219
+ // get any sibling gateways
1220
+ $other_gateway_ids = array_diff( $this->get_plugin()->get_gateway_ids(), array( $this->get_id() ) );
1221
+ $configured_other_gateway_ids = array();
1222
+ $inherit_settings_other_gateway_ids = array();
1223
+
1224
+ // determine if any sibling gateways have any configured shared settings
1225
+ foreach ( $other_gateway_ids as $other_gateway_id ) {
1226
+
1227
+ $other_gateway_settings = $this->get_plugin()->get_gateway_settings( $other_gateway_id );
1228
+
1229
+ // if the other gateway isn't also trying to inherit settings...
1230
+ if ( isset( $other_gateway_settings['inherit_settings'] ) && 'yes' == $other_gateway_settings['inherit_settings'] ) {
1231
+ $inherit_settings_other_gateway_ids[] = $other_gateway_id;
1232
+ }
1233
+
1234
+ foreach ( $this->shared_settings as $setting_name ) {
1235
+
1236
+ // if at least one shared setting is configured in the other gateway
1237
+ if ( isset( $other_gateway_settings[ $setting_name ] ) && $other_gateway_settings[ $setting_name ] ) {
1238
+
1239
+ $configured_other_gateway_ids[] = $other_gateway_id;
1240
+ break;
1241
+ }
1242
+ }
1243
+ }
1244
+
1245
+ $form_fields['connection_settings'] = array(
1246
+ 'title' => esc_html__( 'Connection Settings', 'woocommerce-square' ),
1247
+ 'type' => 'title',
1248
+ );
1249
+
1250
+ // disable the field if the sibling gateway is already inheriting settings
1251
+ $form_fields['inherit_settings'] = array(
1252
+ 'title' => esc_html__( 'Share connection settings', 'woocommerce-square' ),
1253
+ 'type' => 'checkbox',
1254
+ 'label' => esc_html__( 'Use connection/authentication settings from other gateway', 'woocommerce-square' ),
1255
+ 'default' => count( $configured_other_gateway_ids ) > 0 ? 'yes' : 'no',
1256
+ 'disabled' => count( $inherit_settings_other_gateway_ids ) > 0 ? true : false,
1257
+ 'description' => count( $inherit_settings_other_gateway_ids ) > 0 ? esc_html__( 'Disabled because the other gateway is using these settings', 'woocommerce-square' ) : '',
1258
+ );
1259
+
1260
+ return $form_fields;
1261
+ }
1262
+
1263
+
1264
+ /**
1265
+ * Adds the enable Card Security Code form fields
1266
+ *
1267
+ * @since 3.0.0
1268
+ * @param array $form_fields gateway form fields
1269
+ * @return array $form_fields gateway form fields
1270
+ */
1271
+ protected function add_csc_form_fields( $form_fields ) {
1272
+
1273
+ $form_fields['enable_csc'] = array(
1274
+ 'title' => esc_html__( 'Card Verification (CSC)', 'woocommerce-square' ),
1275
+ 'label' => esc_html__( 'Display the Card Security Code (CV2) field on checkout', 'woocommerce-square' ),
1276
+ 'type' => 'checkbox',
1277
+ 'default' => 'yes',
1278
+ );
1279
+
1280
+ if ( $this->supports_tokenization() ) {
1281
+
1282
+ $form_fields['enable_token_csc'] = array(
1283
+ 'title' => esc_html__( 'Saved Card Verification', 'woocommerce-square' ),
1284
+ 'label' => esc_html__( 'Display the Card Security Code field when paying with a saved card', 'woocommerce-square' ),
1285
+ 'type' => 'checkbox',
1286
+ 'default' => 'yes',
1287
+ );
1288
+ }
1289
+
1290
+ return $form_fields;
1291
+ }
1292
+
1293
+
1294
+ /**
1295
+ * Displays settings page with some additional javascript for hiding conditional fields.
1296
+ *
1297
+ * @see \WC_Settings_API::admin_options()
1298
+ *
1299
+ * @since 3.0.0
1300
+ */
1301
+ public function admin_options() {
1302
+
1303
+ parent::admin_options();
1304
+
1305
+ ?>
1306
+ <style type="text/css">.nowrap { white-space: nowrap; }</style>
1307
+ <?php
1308
+
1309
+ if ( isset( $this->form_fields['enable_csc'] ) ) {
1310
+
1311
+ // add inline javascript to show/hide any shared settings fields as needed
1312
+ ob_start();
1313
+ ?>
1314
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_enable_csc' ).change( function() {
1315
+
1316
+ var enabled = $( this ).is( ':checked' );
1317
+
1318
+ if ( enabled ) {
1319
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_enable_token_csc' ).closest( 'tr' ).show();
1320
+ } else {
1321
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_enable_token_csc' ).closest( 'tr' ).hide();
1322
+ }
1323
+
1324
+ } ).change();
1325
+ <?php
1326
+
1327
+ wc_enqueue_js( ob_get_clean() );
1328
+
1329
+ }
1330
+
1331
+ // if transaction types are supported, show/hide the "charge virtual-only" setting
1332
+ if ( isset( $this->form_fields['transaction_type'] ) ) {
1333
+
1334
+ // add inline javascript
1335
+ ob_start();
1336
+ ?>
1337
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_transaction_type' ).change( function() {
1338
+
1339
+ var transaction_type = $( this ).val();
1340
+ var hidden_settings = $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_charge_virtual_orders, #woocommerce_<?php echo esc_js( $this->get_id() ); ?>_enable_partial_capture, #woocommerce_<?php echo esc_js( $this->get_id() ); ?>_enable_paid_capture' ).closest( 'tr' );
1341
+
1342
+ if ( '<?php echo esc_js( self::TRANSACTION_TYPE_AUTHORIZATION ); ?>' === transaction_type ) {
1343
+ $( hidden_settings ).show();
1344
+ } else {
1345
+ $( hidden_settings ).hide();
1346
+ }
1347
+
1348
+ } ).change();
1349
+ <?php
1350
+
1351
+ wc_enqueue_js( ob_get_clean() );
1352
+ }
1353
+
1354
+ // if there's more than one environment include the environment settings switcher code
1355
+ if ( count( $this->get_environments() ) > 1 ) {
1356
+
1357
+ // add inline javascript
1358
+ ob_start();
1359
+ ?>
1360
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_environment' ).change( function() {
1361
+
1362
+ // inherit settings from other gateway?
1363
+ var inheritSettings = $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_inherit_settings' ).is( ':checked' );
1364
+
1365
+ var environment = $( this ).val();
1366
+
1367
+ // hide all environment-dependant fields
1368
+ $( '.environment-field' ).closest( 'tr' ).hide();
1369
+
1370
+ // show the currently configured environment fields that are not also being hidden as any shared settings
1371
+ var $environmentFields = $( '.' + environment + '-field' );
1372
+ if ( inheritSettings ) {
1373
+ $environmentFields = $environmentFields.not( '.shared-settings-field' );
1374
+ }
1375
+
1376
+ $environmentFields.not( '.hidden' ).closest( 'tr' ).show();
1377
+
1378
+ } ).change();
1379
+ <?php
1380
+
1381
+ wc_enqueue_js( ob_get_clean() );
1382
+
1383
+ }
1384
+
1385
+ if ( ! empty( $this->shared_settings ) ) {
1386
+
1387
+ // add inline javascript to show/hide any shared settings fields as needed
1388
+ ob_start();
1389
+ ?>
1390
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_inherit_settings' ).change( function() {
1391
+
1392
+ var enabled = $( this ).is( ':checked' );
1393
+
1394
+ if ( enabled ) {
1395
+ $( '.shared-settings-field' ).closest( 'tr' ).hide();
1396
+ } else {
1397
+ // show the fields
1398
+ $( '.shared-settings-field' ).closest( 'tr' ).show();
1399
+
1400
+ // hide any that may not be available for the currently selected environment
1401
+ $( '#woocommerce_<?php echo esc_js( $this->get_id() ); ?>_environment' ).change();
1402
+ }
1403
+
1404
+ } ).change();
1405
+ <?php
1406
+
1407
+ wc_enqueue_js( ob_get_clean() );
1408
+
1409
+ }
1410
+
1411
+ }
1412
+
1413
+
1414
+ /**
1415
+ * Checks for proper gateway configuration including:
1416
+ *
1417
+ * + gateway enabled
1418
+ * + correct configuration (gateway specific)
1419
+ * + any dependencies met
1420
+ * + required currency
1421
+ * + required country
1422
+ *
1423
+ * @since 3.0.0
1424
+ * @see WC_Payment_Gateway::is_available()
1425
+ * @return true if this gateway is available for checkout, false otherwise
1426
+ */
1427
+ public function is_available() {
1428
+
1429
+ // is enabled check
1430
+ $is_available = parent::is_available();
1431
+
1432
+ // proper configuration
1433
+ if ( ! $this->is_configured() ) {
1434
+ $is_available = false;
1435
+ }
1436
+
1437
+ // all plugin dependencies met
1438
+ if ( count( $this->get_plugin()->get_dependency_handler()->get_missing_php_extensions() ) > 0 ) {
1439
+ $is_available = false;
1440
+ }
1441
+
1442
+ // any required currencies?
1443
+ if ( ! $this->currency_is_accepted() ) {
1444
+ $is_available = false;
1445
+ }
1446
+
1447
+ // any required countries?
1448
+ if ( $this->countries && WC()->customer ) {
1449
+
1450
+ $customer_country = WC()->customer->get_billing_country();
1451
+
1452
+ if ( $customer_country && ! in_array( $customer_country, $this->countries, true ) ) {
1453
+ $is_available = false;
1454
+ }
1455
+ }
1456
+
1457
+ /**
1458
+ * Payment Gateway Is Available Filter.
1459
+ *
1460
+ * Allow actors to modify whether the gateway is available or not.
1461
+ *
1462
+ * @since 3.0.0
1463
+ * @param bool $is_available
1464
+ */
1465
+ return apply_filters( 'wc_gateway_' . $this->get_id() . '_is_available', $is_available );
1466
+ }
1467
+
1468
+
1469
+ /**
1470
+ * Returns true if the gateway is properly configured to perform transactions
1471
+ *
1472
+ * @since 3.0.0
1473
+ * @see Payment_Gateway::is_configured()
1474
+ * @return boolean true if the gateway is properly configured
1475
+ */
1476
+ protected function is_configured() {
1477
+ // override this to check for gateway-specific required settings (user names, passwords, secret keys, etc)
1478
+ return true;
1479
+ }
1480
+
1481
+ /**
1482
+ * Returns the payment method image URL (if any) for the given $type, ie
1483
+ * if $type is 'amex' a URL to the american express card icon will be
1484
+ * returned.
1485
+ *
1486
+ * @since 3.0.0
1487
+ * @param string $type the payment method cc type or name
1488
+ * @return string the image URL or null
1489
+ */
1490
+ public function get_payment_method_image_url( $type ) {
1491
+
1492
+ $image_type = strtolower( $type );
1493
+
1494
+ if ( 'card' === $type ) {
1495
+ $image_type = 'cc-plain';
1496
+ }
1497
+
1498
+ /**
1499
+ * Payment Gateway Fallback to PNG Filter.
1500
+ *
1501
+ * Allow actors to enable the use of PNGs over SVGs for payment icon images.
1502
+ *
1503
+ * @since 3.0.0
1504
+ * @param bool $use_svg true by default, false to use PNGs
1505
+ */
1506
+ $image_extension = apply_filters( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_use_svg', true ) ? '.svg' : '.png';
1507
+
1508
+ // first, is the card image available within the plugin?
1509
+ if ( is_readable( $this->get_plugin()->get_payment_gateway_framework_assets_path() . '/images/card-' . $image_type . $image_extension ) ) {
1510
+ return \WC_HTTPS::force_https_url( $this->get_plugin()->get_payment_gateway_framework_assets_url() . '/images/card-' . $image_type . $image_extension );
1511
+ }
1512
+
1513
+ // default: is the card image available within the framework?
1514
+ if ( is_readable( $this->get_plugin()->get_payment_gateway_framework_assets_path() . '/images/card-' . $image_type . $image_extension ) ) {
1515
+ return \WC_HTTPS::force_https_url( $this->get_plugin()->get_payment_gateway_framework_assets_url() . '/images/card-' . $image_type . $image_extension );
1516
+ }
1517
+
1518
+ return null;
1519
+ }
1520
+
1521
+
1522
+ /**
1523
+ * Add payment and transaction information as class members of WC_Order
1524
+ * instance. The standard information that can be added includes:
1525
+ *
1526
+ * $order->payment_total - the payment total
1527
+ * $order->customer_id - optional payment gateway customer id (useful for tokenized payments, etc)
1528
+ * $order->payment->type - one of 'credit_card' or 'check'
1529
+ * $order->description - an order description based on the order
1530
+ * $order->unique_transaction_ref - a combination of order number + retry count, should provide a unique value for each transaction attempt
1531
+ *
1532
+ * Note that not all gateways will necessarily pass or require all of the
1533
+ * above. These represent the most common attributes used among a variety
1534
+ * of gateways, it's up to the specific gateway implementation to make use
1535
+ * of, or ignore them, or add custom ones by overridding this method.
1536
+ *
1537
+ * The returned order is expected to be used in a transaction request.
1538
+ *
1539
+ * @since 3.0.0
1540
+ * @param int|\WC_Order $order the order or order ID being processed
1541
+ * @return \WC_Order object with payment and transaction information attached
1542
+ */
1543
+ public function get_order( $order ) {
1544
+
1545
+ if ( is_numeric( $order ) ) {
1546
+ $order = wc_get_order( $order );
1547
+ }
1548
+
1549
+ // set payment total here so it can be modified for later by add-ons like subscriptions which may need to charge an amount different than the get_total()
1550
+ $order->payment_total = number_format( $order->get_total(), 2, '.', '' );
1551
+
1552
+ $order->customer_id = '';
1553
+
1554
+ // logged in customer?
1555
+ if ( 0 != $order->get_user_id() && false !== ( $customer_id = $this->get_customer_id( $order->get_user_id(), array( 'order' => $order ) ) ) ) {
1556
+ $order->customer_id = $customer_id;
1557
+ }
1558
+
1559
+ // add payment info
1560
+ $order->payment = new \stdClass();
1561
+
1562
+ // payment type (credit_card/check/etc)
1563
+ $order->payment->type = str_replace( '-', '_', $this->get_payment_type() );
1564
+
1565
+ /* translators: Placeholders: %1$s - site title, %2$s - order number */
1566
+ $order->description = sprintf( esc_html__( '%1$s - Order %2$s', 'woocommerce-square' ), wp_specialchars_decode( Square_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() );
1567
+
1568
+ $order = $this->get_order_with_unique_transaction_ref( $order );
1569
+
1570
+ /**
1571
+ * Filters the base order for a payment transaction.
1572
+ *
1573
+ * Actors can use this filter to adjust or add additional information to
1574
+ * the order object that gateways use for processing transactions.
1575
+ *
1576
+ * @since 3.0.0
1577
+ *
1578
+ * @param \WC_Order $order order object
1579
+ * @param Payment_Gateway $this payment gateway instance
1580
+ */
1581
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_get_order_base', $order, $this );
1582
+ }
1583
+
1584
+
1585
+ /**
1586
+ * Completes an order payment.
1587
+ *
1588
+ * This method marks the order with an appropriate status, and adds a relevant order note.
1589
+ *
1590
+ * @since 3.0.0
1591
+ *
1592
+ * @param \WC_Order $order order object
1593
+ * @param Payment_Gateway_API_Response $response response object
1594
+ * @throws \Exception
1595
+ */
1596
+ protected function complete_payment( \WC_Order $order, Payment_Gateway_API_Response $response ) {
1597
+
1598
+ if ( self::PAYMENT_TYPE_CREDIT_CARD == $response->get_payment_type() ) {
1599
+ $order->add_order_note( $this->get_credit_card_transaction_approved_message( $order, $response ) );
1600
+ } else {
1601
+ $message_method = 'get_' . $response->get_payment_type() . '_transaction_approved_message';
1602
+
1603
+ if ( is_callable( array( $this, $message_method ) ) ) {
1604
+ $order->add_order_note( $this->$message_method( $order, $response ) );
1605
+ }
1606
+ }
1607
+
1608
+ if ( $response->transaction_held() || ( $this->supports_credit_card_authorization() && $this->perform_credit_card_authorization( $order ) ) ) {
1609
+
1610
+ $message = $this->supports_credit_card_authorization() && $this->perform_credit_card_authorization( $order ) ? __( 'Authorization only transaction', 'woocommerce-square' ) : $response->get_status_message();
1611
+
1612
+ $this->mark_order_as_held( $order, $message, $response );
1613
+
1614
+ wc_reduce_stock_levels( $order->get_id() );
1615
+
1616
+ } else {
1617
+
1618
+ $order->payment_complete();
1619
+ }
1620
+
1621
+ /**
1622
+ * Fires after a payment transaction is successfully completed.
1623
+ *
1624
+ * @since 3.0.0
1625
+ *
1626
+ * @param \WC_Order $order order object
1627
+ * @param Payment_Gateway $gateway gateway object
1628
+ */
1629
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_complete_payment', $order, $this );
1630
+ }
1631
+
1632
+
1633
+ /** Capture Methods ***********************************************************************************************/
1634
+
1635
+
1636
+ /**
1637
+ * Builds the capture handler instance.
1638
+ *
1639
+ * @since 3.0.0
1640
+ */
1641
+ public function init_capture_handler() {
1642
+
1643
+ $this->capture_handler = new Capture( $this );
1644
+ }
1645
+
1646
+
1647
+ /**
1648
+ * Gets the capture handler instance.
1649
+ *
1650
+ * @since 3.0.0
1651
+ *
1652
+ * @return Payment_Gateway\Handlers\Capture
1653
+ */
1654
+ public function get_capture_handler() {
1655
+
1656
+ return $this->capture_handler;
1657
+ }
1658
+
1659
+
1660
+ /**
1661
+ * Gets an order object with payment data added for use in credit card capture transactions.
1662
+ *
1663
+ * This was intentionally not moved to the capture handler since we'll likely be refactoring how this information is
1664
+ * set in the future, and plenty of gateways override it.
1665
+ *
1666
+ * @since 3.0.0
1667
+ *
1668
+ * @param \WC_Order|int $order the order being processed
1669
+ * @param float|null $amount amount to capture or null for the full order amount
1670
+ * @return \WC_Order
1671
+ */
1672
+ public function get_order_for_capture( $order, $amount = null ) {
1673
+
1674
+ if ( is_numeric( $order ) ) {
1675
+ $order = wc_get_order( $order );
1676
+ }
1677
+
1678
+ // add capture info
1679
+ $order->capture = new \stdClass();
1680
+
1681
+ $total_captured = $this->get_order_meta( $order, 'capture_total' );
1682
+
1683
+ // if no amount is specified, as in a bulk capture situation, always use the amount remaining
1684
+ if ( ! $amount ) {
1685
+ $amount = (float) $order->get_total() - (float) $total_captured;
1686
+ }
1687
+
1688
+ $order->capture->amount = Square_Helper::number_format( $amount );
1689
+
1690
+ /* translators: Placeholders: %1$s - site title, %2$s - order number. Definitions: Capture as in capture funds from a credit card. */
1691
+ $order->capture->description = sprintf( esc_html__( '%1$s - Capture for Order %2$s', 'woocommerce-square' ), wp_specialchars_decode( Square_Helper::get_site_name() ), $order->get_order_number() );
1692
+ $order->capture->trans_id = $this->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'trans_id' );
1693
+
1694
+ /**
1695
+ * Direct Gateway Capture Get Order Filter.
1696
+ *
1697
+ * Allow actors to modify the order object used for performing charge captures.
1698
+ *
1699
+ * @since 3.0.0
1700
+ * @param \WC_Order $order order object
1701
+ * @param Payment_Gateway $this instance
1702
+ */
1703
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_get_order_for_capture', $order, $this );
1704
+ }
1705
+
1706
+ /**
1707
+ * Processes a refund.
1708
+ *
1709
+ * @since 3.0.0
1710
+ *
1711
+ * @param int $order_id order being refunded
1712
+ * @param float $amount refund amount
1713
+ * @param string $reason user-entered reason text for refund
1714
+ * @return bool|\WP_Error true on success, or a WP_Error object on failure/error
1715
+ */
1716
+ public function process_refund( $order_id, $amount = null, $reason = '' ) {
1717
+
1718
+ // add transaction-specific refund info (amount, reason, transaction IDs, etc)
1719
+ $order = $this->get_order_for_refund( $order_id, $amount, $reason );
1720
+
1721
+ // let implementations/actors error out early (e.g. order is missing required data for refund, etc)
1722
+ if ( is_wp_error( $order ) ) {
1723
+ return $order;
1724
+ }
1725
+
1726
+ // if captures are supported and the order has an authorized, but not captured charge, void it instead
1727
+ if ( $this->supports_voids() && ! $this->get_capture_handler()->is_order_captured( $order ) ) {
1728
+ return $this->process_void( $order );
1729
+ }
1730
+
1731
+ try {
1732
+
1733
+ $response = $response = $this->get_api()->refund( $order );
1734
+
1735
+ // allow gateways to void an order in response to a refund attempt
1736
+ if ( $this->supports_voids() && $this->maybe_void_instead_of_refund( $order, $response ) ) {
1737
+ return $this->process_void( $order );
1738
+ }
1739
+
1740
+ if ( $response->transaction_approved() ) {
1741
+
1742
+ // add standard refund-specific transaction data
1743
+ $this->add_refund_data( $order, $response );
1744
+
1745
+ // add order note
1746
+ $this->add_refund_order_note( $order, $response );
1747
+
1748
+ // when full amount is refunded, update status to refunded
1749
+ if ( $order->get_total() == $order->get_total_refunded() ) {
1750
+ $this->mark_order_as_refunded( $order );
1751
+ }
1752
+
1753
+ /**
1754
+ * Fires after a refund is successfully processed.
1755
+ *
1756
+ * @since 3.0.0
1757
+ *
1758
+ * @param \WC_Order $order order object
1759
+ * @param Payment_Gateway $gateway payment gateway instance
1760
+ */
1761
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_refund_processed', $order, $this );
1762
+
1763
+ return true;
1764
+
1765
+ } else {
1766
+
1767
+ $error = $this->get_refund_failed_wp_error( $response->get_status_code(), $response->get_status_message() );
1768
+
1769
+ $order->add_order_note( $error->get_error_message() );
1770
+
1771
+ return $error;
1772
+ }
1773
+
1774
+ } catch ( \Exception $e ) {
1775
+
1776
+ $error = $this->get_refund_failed_wp_error( $e->getCode(), $e->getMessage() );
1777
+
1778
+ $order->add_order_note( $error->get_error_message() );
1779
+
1780
+ return $error;
1781
+ }
1782
+ }
1783
+
1784
+ /**
1785
+ * Add refund information as class members of WC_Order
1786
+ * instance for use in refund transactions. Standard information includes:
1787
+ *
1788
+ * $order->refund->amount = refund amount
1789
+ * $order->refund->reason = user-entered reason text for the refund
1790
+ * $order->refund->trans_id = the ID of the original payment transaction for the order
1791
+ *
1792
+ * Payment gateway implementations can override this to add their own
1793
+ * refund-specific data
1794
+ *
1795
+ * @since 3.0.0
1796
+ *
1797
+ * @param \WC_Order|int $order order being processed
1798
+ * @param float $amount refund amount
1799
+ * @param string $reason optional refund reason text
1800
+ * @return \WC_Order|\WP_Error object with refund information attached
1801
+ */
1802
+ protected function get_order_for_refund( $order, $amount, $reason ) {
1803
+
1804
+ if ( is_numeric( $order ) ) {
1805
+ $order = wc_get_order( $order );
1806
+ }
1807
+
1808
+ // add refund info
1809
+ $order->refund = new \stdClass();
1810
+ $order->refund->amount = number_format( $amount, 2, '.', '' );
1811
+
1812
+ /* translators: Placeholders: %1$s - site title, %2$s - order number */
1813
+ $order->refund->reason = $reason ? $reason : sprintf( esc_html__( '%1$s - Refund for Order %2$s', 'woocommerce-square' ), esc_html( Square_Helper::get_site_name() ), $order->get_order_number() );
1814
+
1815
+ // almost all gateways require the original transaction ID, so include it by default
1816
+ $order->refund->trans_id = $this->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'trans_id' );
1817
+
1818
+ /**
1819
+ * Payment Gateway Get Order For Refund Filter.
1820
+ *
1821
+ * Allow actors to modify the order object used for refund transactions.
1822
+ *
1823
+ * @since 3.0.0
1824
+ *
1825
+ * @param \WC_Order|\WP_Error $order order object
1826
+ * @param Payment_Gateway $this instance
1827
+ */
1828
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_get_order_for_refund', $order, $this );
1829
+ }
1830
+
1831
+
1832
+ /**
1833
+ * Adds the standard refund transaction data to the order.
1834
+ *
1835
+ * Note that refunds can be performed multiple times for a single order so
1836
+ * transaction IDs keys are not unique
1837
+ *
1838
+ * @since 3.0.0
1839
+ *
1840
+ * @param \WC_Order $order the order object
1841
+ * @param Payment_Gateway_API_Response $response transaction response
1842
+ */
1843
+ protected function add_refund_data( \WC_Order $order, $response ) {
1844
+
1845
+ // indicate the order was refunded along with the refund amount
1846
+ $this->add_order_meta( $order, 'refund_amount', $order->refund->amount );
1847
+
1848
+ // add refund transaction ID
1849
+ if ( $response && $response->get_transaction_id() ) {
1850
+ $this->add_order_meta( $order, 'refund_trans_id', $response->get_transaction_id() );
1851
+ }
1852
+ }
1853
+
1854
+ /**
1855
+ * Adds an order note with the amount and (optional) refund transaction ID.
1856
+ *
1857
+ * @since 3.0.0
1858
+ *
1859
+ * @param \WC_Order $order order object
1860
+ * @param Payment_Gateway_API_Response $response transaction response
1861
+ */
1862
+ protected function add_refund_order_note( \WC_Order $order, $response ) {
1863
+
1864
+ $message = sprintf(
1865
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - a monetary amount */
1866
+ esc_html__( '%1$s Refund in the amount of %2$s approved.', 'woocommerce-square' ),
1867
+ $this->get_method_title(),
1868
+ wc_price( $order->refund->amount, array( 'currency' => Order_Compatibility::get_prop( $order, 'currency', 'view' ) ) )
1869
+ );
1870
+
1871
+ // adds the transaction id (if any) to the order note
1872
+ if ( $response->get_transaction_id() ) {
1873
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
1874
+ }
1875
+
1876
+ $order->add_order_note( $message );
1877
+ }
1878
+
1879
+
1880
+ /**
1881
+ * Builds the WP_Error object for a failed refund.
1882
+ *
1883
+ * @since 3.0.0
1884
+ *
1885
+ * @param int|string $error_code error code
1886
+ * @param string $error_message error message
1887
+ * @return \WP_Error suitable for returning from the process_refund() method
1888
+ */
1889
+ protected function get_refund_failed_wp_error( $error_code, $error_message ) {
1890
+
1891
+ if ( $error_code ) {
1892
+ $message = sprintf(
1893
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - error code, %3$s - error message */
1894
+ esc_html__( '%1$s Refund Failed: %2$s - %3$s', 'woocommerce-square' ),
1895
+ $this->get_method_title(),
1896
+ $error_code,
1897
+ $error_message
1898
+ );
1899
+ } else {
1900
+ $message = sprintf(
1901
+ /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - error message */
1902
+ esc_html__( '%1$s Refund Failed: %2$s', 'woocommerce-square' ),
1903
+ $this->get_method_title(),
1904
+ $error_message
1905
+ );
1906
+ }
1907
+
1908
+ return new \WP_Error( 'wc_' . $this->get_id() . '_refund_failed', $message );
1909
+ }
1910
+
1911
+
1912
+ /**
1913
+ * Mark an order as refunded. This should only be used when the full order
1914
+ * amount has been refunded.
1915
+ *
1916
+ * @since 3.0.0
1917
+ *
1918
+ * @param \WC_Order $order order object
1919
+ */
1920
+ public function mark_order_as_refunded( $order ) {
1921
+
1922
+ /* translators: Placeholders: %s - payment gateway title (such as Authorize.net, Braintree, etc) */
1923
+ $order_note = sprintf( esc_html__( '%s Order completely refunded.', 'woocommerce-square' ), $this->get_method_title() );
1924
+
1925
+ // Mark order as refunded if not already set
1926
+ if ( ! $order->has_status( 'refunded' ) ) {
1927
+ $order->update_status( 'refunded', $order_note );
1928
+ } else {
1929
+ $order->add_order_note( $order_note );
1930
+ }
1931
+ }
1932
+
1933
+
1934
+ /** Void feature ********************************************************/
1935
+
1936
+
1937
+ /**
1938
+ * Returns true if this is gateway that supports voids
1939
+ *
1940
+ * @since 3.0.0
1941
+ * @return boolean true if the gateway supports voids
1942
+ */
1943
+ public function supports_voids() {
1944
+
1945
+ return $this->supports( self::FEATURE_VOIDS ) && $this->supports_credit_card_capture();
1946
+ }
1947
+
1948
+
1949
+ /**
1950
+ * Allow gateways to void an order that was attempted to be refunded. This is
1951
+ * particularly useful for gateways that can void an authorized & captured
1952
+ * charge that has not yet settled (e.g. Authorize.net AIM/CIM)
1953
+ *
1954
+ * @since 3.0.0
1955
+ *
1956
+ * @param \WC_Order $order order
1957
+ * @param Payment_Gateway_API_Response $response refund response
1958
+ * @return boolean true if a void should be performed for the given order/response
1959
+ */
1960
+ protected function maybe_void_instead_of_refund( $order, $response ) {
1961
+
1962
+ return false;
1963
+ }
1964
+
1965
+
1966
+ /**
1967
+ * Processes a void order.
1968
+ *
1969
+ * @since 3.0.0
1970
+ *
1971
+ * @param \WC_Order $order order object (with refund class member already added)
1972
+ * @return bool|\WP_Error true on success, or a WP_Error object on failure/error
1973
+ */
1974
+ protected function process_void( \WC_Order $order ) {
1975
+
1976
+ // partial voids are not supported
1977
+ if ( $order->refund->amount != $order->get_total() ) {
1978
+ return new \WP_Error( 'wc_' . $this->get_id() . '_void_error', esc_html__( 'Oops, you cannot partially void this order. Please use the full order amount.', 'woocommerce-square' ), 500 );
1979
+ }
1980
+
1981
+ try {
1982
+
1983
+ $response = $this->get_api()->void( $order );
1984
+
1985
+ if ( $response->transaction_approved() ) {
1986
+
1987
+ // add standard void-specific transaction data
1988
+ $this->add_void_data( $order, $response );
1989
+
1990
+ // update order status to "refunded" and add an order note
1991
+ $this->mark_order_as_voided( $order, $response );
1992
+
1993
+ return true;
1994
+
1995
+ } else {
1996
+
1997
+ $error = $this->get_void_failed_wp_error( $response->get_status_code(), $response->get_status_message() );
1998
+
1999
+ $order->add_order_note( $error->get_error_message() );
2000
+
2001
+ return $error;
2002
+ }
2003
+
2004
+ } catch ( \Exception $e ) {
2005
+
2006
+ $error = $this->get_void_failed_wp_error( $e->getCode(), $e->getMessage() );
2007
+
2008
+ $order->add_order_note( $error->get_error_message() );
2009
+
2010
+ return $error;
2011
+ }
2012
+ }
2013
+
2014
+
2015
+ /**
2016
+ * Adds the standard void transaction data to the order.
2017
+ *
2018
+ * @since 3.0.0
2019
+ *
2020
+ * @param \WC_Order $order the order object
2021
+ * @param Payment_Gateway_API_Response $response transaction response
2022
+ */
2023
+ protected function add_void_data( \WC_Order $order, $response ) {
2024
+
2025
+ // indicate the order was voided along with the amount
2026
+ $this->update_order_meta( $order, 'void_amount', $order->refund->amount );
2027
+
2028
+ // add refund transaction ID
2029
+ if ( $response && $response->get_transaction_id() ) {
2030
+ $this->add_order_meta( $order, 'void_trans_id', $response->get_transaction_id() );
2031
+ }
2032
+ }
2033
+
2034
+ /**
2035
+ * Builds the WP_Error object for a failed void.
2036
+ *
2037
+ * @since 3.0.0
2038
+ *
2039
+ * @param int|string $error_code error code
2040
+ * @param string $error_message error message
2041
+ * @return \WP_Error suitable for returning from the process_refund() method
2042
+ */
2043
+ protected function get_void_failed_wp_error( $error_code, $error_message ) {
2044
+
2045
+ if ( $error_code ) {
2046
+ $message = sprintf(
2047
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - error code, %3$s - error message. Void as in to void an order. */
2048
+ esc_html__( '%1$s Void Failed: %2$s - %3$s', 'woocommerce-square' ),
2049
+ $this->get_method_title(),
2050
+ $error_code,
2051
+ $error_message
2052
+ );
2053
+ } else {
2054
+ $message = sprintf(
2055
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - error message. Void as in to void an order. */
2056
+ esc_html__( '%1$s Void Failed: %2$s', 'woocommerce-square' ),
2057
+ $this->get_method_title(),
2058
+ $error_message
2059
+ );
2060
+ }
2061
+
2062
+ return new \WP_Error( 'wc_' . $this->get_id() . '_void_failed', $message );
2063
+ }
2064
+
2065
+
2066
+ /**
2067
+ * Marks an order as voided.
2068
+ *
2069
+ * Because WC has no status for "void", we use refunded.
2070
+ *
2071
+ * @since 3.0.0
2072
+ *
2073
+ * @param \WC_Order $order order object
2074
+ * @param Payment_Gateway_API_Response $response object
2075
+ */
2076
+ public function mark_order_as_voided( $order, $response ) {
2077
+
2078
+ $message = sprintf(
2079
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - a monetary amount. Void as in to void an order. */
2080
+ esc_html__( '%1$s Void in the amount of %2$s approved.', 'woocommerce-square' ),
2081
+ $this->get_method_title(),
2082
+ wc_price( $order->refund->amount, array( 'currency' => Order_Compatibility::get_prop( $order, 'currency', 'view' ) ) )
2083
+ );
2084
+
2085
+ // adds the transaction id (if any) to the order note
2086
+ if ( $response->get_transaction_id() ) {
2087
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
2088
+ }
2089
+
2090
+ // mark order as cancelled, since no money was actually transferred
2091
+ if ( ! $order->has_status( 'cancelled' ) ) {
2092
+
2093
+ $this->voided_order_message = $message;
2094
+
2095
+ add_filter( 'woocommerce_order_fully_refunded_status', array( $this, 'maybe_cancel_voided_order' ), 10, 2 );
2096
+
2097
+ } else {
2098
+
2099
+ $order->add_order_note( $message );
2100
+ }
2101
+ }
2102
+
2103
+
2104
+ /**
2105
+ * Maybe change the order status for a voided order to cancelled
2106
+ *
2107
+ * @hooked woocommerce_order_fully_refunded_status filter
2108
+ *
2109
+ * @see Payment_Gateway::mark_order_as_voided()
2110
+ * @since 3.0.0
2111
+ * @param string $order_status default order status for fully refunded orders
2112
+ * @param int $order_id order ID
2113
+ * @return string 'cancelled'
2114
+ */
2115
+ public function maybe_cancel_voided_order( $order_status, $order_id ) {
2116
+
2117
+ if ( empty( $this->voided_order_message ) ) {
2118
+ return $order_status;
2119
+ }
2120
+
2121
+ $order = wc_get_order( $order_id );
2122
+
2123
+ // no way to set the order note with the status change
2124
+ $order->add_order_note( $this->voided_order_message );
2125
+
2126
+ return 'cancelled';
2127
+ }
2128
+
2129
+
2130
+ /**
2131
+ * Returns the $order object with a unique transaction ref member added.
2132
+ *
2133
+ * @since 3.0.0
2134
+ *
2135
+ * @param \WC_Order $order the order object
2136
+ * @return \WC_Order order object with member named unique_transaction_ref
2137
+ */
2138
+ protected function get_order_with_unique_transaction_ref( $order ) {
2139
+
2140
+ $order_id = Order_Compatibility::get_prop( $order, 'id' );
2141
+
2142
+ // generate a unique retry count
2143
+ if ( is_numeric( $this->get_order_meta( $order_id, 'retry_count' ) ) ) {
2144
+ $retry_count = $this->get_order_meta( $order_id, 'retry_count' );
2145
+
2146
+ $retry_count++;
2147
+ } else {
2148
+ $retry_count = 0;
2149
+ }
2150
+
2151
+ // keep track of the retry count
2152
+ $this->update_order_meta( $order, 'retry_count', $retry_count );
2153
+
2154
+ // generate a unique transaction ref based on the order number and retry count, for gateways that require a unique identifier for every transaction request
2155
+ $order->unique_transaction_ref = ltrim( $order->get_order_number(), esc_html_x( '#', 'hash before order number', 'woocommerce-square' ) ) . ( $retry_count > 0 ? '-' . $retry_count : '' );
2156
+
2157
+ return $order;
2158
+ }
2159
+
2160
+
2161
+ /**
2162
+ * Called after an unsuccessful transaction attempt.
2163
+ *
2164
+ * @since 3.0.0
2165
+ *
2166
+ * @param \WC_Order $order the order
2167
+ * @param Payment_Gateway_API_Response $response the transaction response
2168
+ * @return false
2169
+ */
2170
+ protected function do_transaction_failed_result( \WC_Order $order, Payment_Gateway_API_Response $response ) {
2171
+
2172
+ $order_note = '';
2173
+
2174
+ // build the order note with what data we have
2175
+ if ( $response->get_status_code() && $response->get_status_message() ) {
2176
+ /* translators: Placeholders: %1$s - status code, %2$s - status message */
2177
+ $order_note = sprintf( esc_html__( 'Status code %1$s: %2$s', 'woocommerce-square' ), $response->get_status_code(), $response->get_status_message() );
2178
+ } elseif ( $response->get_status_code() ) {
2179
+ /* translators: Placeholders: %s - status code */
2180
+ $order_note = sprintf( esc_html__( 'Status code: %s', 'woocommerce-square' ), $response->get_status_code() );
2181
+ } elseif ( $response->get_status_message() ) {
2182
+ /* translators: Placeholders; %s - status message */
2183
+ $order_note = sprintf( esc_html__( 'Status message: %s', 'woocommerce-square' ), $response->get_status_message() );
2184
+ }
2185
+
2186
+ // add transaction id if there is one
2187
+ if ( $response->get_transaction_id() ) {
2188
+ $order_note .= ' ' . sprintf( esc_html__( 'Transaction ID %s', 'woocommerce-square' ), $response->get_transaction_id() );
2189
+ }
2190
+
2191
+ $this->mark_order_as_failed( $order, $order_note, $response );
2192
+
2193
+ return false;
2194
+ }
2195
+
2196
+
2197
+ /**
2198
+ * Adds the standard transaction data to the order.
2199
+ *
2200
+ * @since 3.0.0
2201
+ *
2202
+ * @param \WC_Order $order the order object
2203
+ * @param Payment_Gateway_API_Response|null $response optional transaction response
2204
+ */
2205
+ public function add_transaction_data( $order, $response = null ) {
2206
+
2207
+ // transaction id if available
2208
+ if ( $response && $response->get_transaction_id() ) {
2209
+
2210
+ $this->update_order_meta( $order, 'trans_id', $response->get_transaction_id() );
2211
+
2212
+ update_post_meta( Order_Compatibility::get_prop( $order, 'id' ), '_transaction_id', $response->get_transaction_id() );
2213
+ }
2214
+
2215
+ // transaction date
2216
+ $this->update_order_meta( $order, 'trans_date', current_time( 'mysql' ) );
2217
+
2218
+ // if there's more than one environment
2219
+ if ( count( $this->get_environments() ) > 1 ) {
2220
+ $this->update_order_meta( $order, 'environment', $this->get_environment() );
2221
+ }
2222
+
2223
+ // customer data
2224
+ if ( $this->supports_customer_id() ) {
2225
+ $this->add_customer_data( $order, $response );
2226
+ }
2227
+
2228
+ if ( isset( $order->payment->token ) && $order->payment->token ) {
2229
+ $this->update_order_meta( $order, 'payment_token', $order->payment->token );
2230
+ }
2231
+
2232
+ // account number
2233
+ if ( isset( $order->payment->account_number ) && $order->payment->account_number ) {
2234
+ $this->update_order_meta( $order, 'account_four', substr( $order->payment->account_number, -4 ) );
2235
+ }
2236
+
2237
+ if ( $this->is_credit_card_gateway() ) {
2238
+
2239
+ // credit card gateway data
2240
+ if ( $response && $response instanceof Payment_Gateway_API_Authorization_Response ) {
2241
+
2242
+ $this->update_order_meta( $order, 'authorization_amount', $order->payment_total );
2243
+
2244
+ if ( $response->get_authorization_code() ) {
2245
+ $this->update_order_meta( $order, 'authorization_code', $response->get_authorization_code() );
2246
+ }
2247
+
2248
+ if ( $order->payment_total > 0 ) {
2249
+
2250
+ // mark as captured
2251
+ if ( $this->perform_credit_card_charge( $order ) ) {
2252
+ $captured = 'yes';
2253
+ } else {
2254
+ $captured = 'no';
2255
+ }
2256
+
2257
+ $this->update_order_meta( $order, 'charge_captured', $captured );
2258
+ }
2259
+ }
2260
+
2261
+ if ( isset( $order->payment->exp_year ) && $order->payment->exp_year && isset( $order->payment->exp_month ) && $order->payment->exp_month ) {
2262
+ $this->update_order_meta( $order, 'card_expiry_date', $order->payment->exp_year . '-' . $order->payment->exp_month );
2263
+ }
2264
+
2265
+ if ( isset( $order->payment->card_type ) && $order->payment->card_type ) {
2266
+ $this->update_order_meta( $order, 'card_type', $order->payment->card_type );
2267
+ }
2268
+ }
2269
+
2270
+ /**
2271
+ * Payment Gateway Add Transaction Data Action.
2272
+ *
2273
+ * Fired after a transaction is processed and provides actors a way to add additional
2274
+ * transactional data to an order given the transaction response object.
2275
+ *
2276
+ * @since 3.0.0
2277
+ *
2278
+ * @param \WC_Order $order order object
2279
+ * @param Payment_Gateway_API_Response|null $response transaction response
2280
+ * @param Payment_Gateway $this instance
2281
+ */
2282
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_add_transaction_data', $order, $response, $this );
2283
+ }
2284
+
2285
+
2286
+ /**
2287
+ * Adds any gateway-specific transaction data to the order.
2288
+ *
2289
+ * @since 3.0.0
2290
+ *
2291
+ * @param \WC_Order $order the order object
2292
+ * @param SquareFramework\PaymentGateway\Api\Payment_Gateway_API_Customer_Response $response the transaction response
2293
+ */
2294
+ public function add_payment_gateway_transaction_data( $order, $response ) {
2295
+ // Optional method
2296
+ }
2297
+
2298
+
2299
+ /**
2300
+ * Add customer data to an order/user if the gateway supports the customer ID
2301
+ * response
2302
+ *
2303
+ * @since 3.0.0
2304
+ *
2305
+ * @param \WC_Order $order order
2306
+ * @param SquareFramework\PaymentGateway\Api\Payment_Gateway_API_Customer_Response $response
2307
+ */
2308
+ protected function add_customer_data( $order, $response = null ) {
2309
+
2310
+ $user_id = $order->get_user_id();
2311
+
2312
+ if ( $response && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) {
2313
+
2314
+ $order->customer_id = $customer_id = $response->get_customer_id();
2315
+
2316
+ } else {
2317
+
2318
+ // default to the customer ID set on the order
2319
+ $customer_id = $order->customer_id;
2320
+ }
2321
+
2322
+ // update the order with the customer ID, note environment is not appended here because it's already available
2323
+ // on the `environment` order meta
2324
+ $this->update_order_meta( $order, 'customer_id', $customer_id );
2325
+
2326
+ // update the user
2327
+ if ( 0 != $user_id ) {
2328
+ $this->update_customer_id( $user_id, $customer_id );
2329
+ }
2330
+ }
2331
+
2332
+
2333
+ /**
2334
+ * Gets the order note message for approved credit card transactions.
2335
+ *
2336
+ * @since 3.0.0
2337
+ *
2338
+ * @param \WC_Order $order order object
2339
+ * @param Payment_Gateway_API_Response $response response object
2340
+ * @return string
2341
+ * @throws \Exception
2342
+ */
2343
+ public function get_credit_card_transaction_approved_message( \WC_Order $order, $response ) {
2344
+
2345
+ $last_four = ! empty( $order->payment->last_four ) ? $order->payment->last_four : substr( $order->payment->account_number, -4 );
2346
+
2347
+ // use direct card type if set, or try to guess it from card number
2348
+ if ( ! empty( $order->payment->card_type ) ) {
2349
+ $card_type = $order->payment->card_type;
2350
+ } elseif ( $first_four = substr( $order->payment->account_number, 0, 4 ) ) {
2351
+ $card_type = Payment_Gateway_Helper::card_type_from_account_number( $first_four );
2352
+ } else {
2353
+ $card_type = 'card';
2354
+ }
2355
+
2356
+ $message = sprintf(
2357
+ /* translators: Placeholders: %1$s - payment method title, %2$s - environment ("Test"), %3$s - transaction type (authorization/charge) */
2358
+ esc_html__( '%1$s %2$s %3$s Approved', 'woocommerce-square' ),
2359
+ $this->get_method_title(),
2360
+ $this->is_test_environment() ? esc_html_x( 'Test', 'noun, software environment', 'woocommerce-square' ) : '',
2361
+ $this->perform_credit_card_authorization( $order ) ? esc_html_x( 'Authorization', 'credit card transaction type', 'woocommerce-square' ) : esc_html_x( 'Charge', 'noun, credit card transaction type', 'woocommerce-square' )
2362
+ );
2363
+
2364
+ if ( $last_four ) {
2365
+
2366
+ $message .= ': ' . sprintf(
2367
+ /* translators: Placeholders: %1$s - credit card type (MasterCard, Visa, etc...), %2$s - last four digits of the card */
2368
+ esc_html__( '%1$s ending in %2$s', 'woocommerce-square' ),
2369
+ Payment_Gateway_Helper::payment_type_to_name( $card_type ),
2370
+ $last_four
2371
+ );
2372
+ }
2373
+
2374
+ // add the expiry date if it is available
2375
+ if ( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ) {
2376
+
2377
+ $message .= ' ' . sprintf(
2378
+ /** translators: Placeholders: %s - credit card expiry date */
2379
+ esc_html__( '(expires %s)', 'woocommerce-square' ),
2380
+ $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 )
2381
+ );
2382
+ }
2383
+
2384
+ // adds the transaction id (if any) to the order note
2385
+ if ( $response->get_transaction_id() ) {
2386
+ /* translators: Placeholders: %s - transaction ID */
2387
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
2388
+ }
2389
+
2390
+ /**
2391
+ * Direct Gateway Credit Card Transaction Approved Order Note Filter.
2392
+ *
2393
+ * Allow actors to modify the order note added when a Credit Card transaction
2394
+ * is approved.
2395
+ *
2396
+ * @since 3.0.0
2397
+ *
2398
+ * @param string $message order note
2399
+ * @param \WC_Order $order order object
2400
+ * @param Payment_Gateway_API_Response $response transaction response
2401
+ * @param Payment_Gateway_Direct $this instance
2402
+ */
2403
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_credit_card_transaction_approved_order_note', $message, $order, $response, $this );
2404
+ }
2405
+
2406
+ /**
2407
+ * Marks the given order as 'on-hold', set an order note and display a message to the customer.
2408
+ *
2409
+ * @since 3.0.0
2410
+ *
2411
+ * @param \WC_Order $order the order
2412
+ * @param string $message a message to display within the order note
2413
+ * @param Payment_Gateway_API_Response $response optional, the transaction response object
2414
+ */
2415
+ public function mark_order_as_held( $order, $message, $response = null ) {
2416
+
2417
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - message (probably reason for the transaction being held for review) */
2418
+ $order_note = sprintf( esc_html__( '%1$s Transaction Held for Review (%2$s)', 'woocommerce-square' ), $this->get_method_title(), $message );
2419
+
2420
+ /**
2421
+ * Held Order Status Filter.
2422
+ *
2423
+ * This filter is deprecated. Use wc_<gateway_id>_held_order_status instead.
2424
+ *
2425
+ * @since 3.0.0
2426
+ *
2427
+ * @param string $order_status 'on-hold' by default
2428
+ * @param \WC_Order $order WC order
2429
+ * @param Payment_Gateway_API_Response $response instance
2430
+ * @param Payment_Gateway $gateway gateway instance
2431
+ */
2432
+ $order_status = apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_held_order_status', 'on-hold', $order, $response, $this );
2433
+
2434
+ /**
2435
+ * Filters the order status that's considered to be "held".
2436
+ *
2437
+ * @since 3.0.0
2438
+ *
2439
+ * @param string $status held order status
2440
+ * @param \WC_Order $order order object
2441
+ * @param Payment_Gateway_API_Response|null $response API response object, if any
2442
+ */
2443
+ $order_status = apply_filters( 'wc_' . $this->get_id() . '_held_order_status', $order_status, $order, $response );
2444
+
2445
+ // mark order as held
2446
+ if ( ! $order->has_status( $order_status ) ) {
2447
+ $order->update_status( $order_status, $order_note );
2448
+ } else {
2449
+ $order->add_order_note( $order_note );
2450
+ }
2451
+
2452
+ // user message
2453
+ $user_message = '';
2454
+ if ( $response && $this->is_detailed_customer_decline_messages_enabled() ) {
2455
+ $user_message = $response->get_user_message();
2456
+ }
2457
+
2458
+ if ( ! $user_message || ( $this->supports_credit_card_authorization() && $this->perform_credit_card_authorization( $order ) ) ) {
2459
+ $user_message = esc_html__( 'Your order has been received and is being reviewed. Thank you for your business.', 'woocommerce-square' );
2460
+ }
2461
+
2462
+ if ( isset( WC()->session ) ) {
2463
+ WC()->session->held_order_received_text = $user_message;
2464
+ }
2465
+ }
2466
+
2467
+
2468
+ /**
2469
+ * Maybe render custom order received text on the thank you page when
2470
+ * an order is held
2471
+ *
2472
+ * If detailed customer decline messages are enabled, this message may
2473
+ * additionally include more detailed information.
2474
+ *
2475
+ * @since 3.0.0
2476
+ *
2477
+ * @param string $text order received text
2478
+ * @param \WC_Order|null $order order object
2479
+ * @return string
2480
+ */
2481
+ public function maybe_render_held_order_received_text( $text, $order ) {
2482
+
2483
+ if ( $order && $order->has_status( 'on-hold' ) && isset( WC()->session->held_order_received_text ) ) {
2484
+
2485
+ $text = WC()->session->held_order_received_text;
2486
+
2487
+ unset( WC()->session->held_order_received_text );
2488
+ }
2489
+
2490
+ return $text;
2491
+ }
2492
+
2493
+
2494
+ /**
2495
+ * Marks the given order as failed and set the order note.
2496
+ *
2497
+ * @since 3.0.0
2498
+ *
2499
+ * @param \WC_Order $order the order
2500
+ * @param string $error_message a message to display inside the "Payment Failed" order note
2501
+ * @param Payment_Gateway_API_Response optional $response the transaction response object
2502
+ */
2503
+ public function mark_order_as_failed( $order, $error_message, $response = null ) {
2504
+
2505
+ /* translators: Placeholders: %1$s - payment gateway title, %2$s - error message; e.g. Order Note: [Payment method] Payment failed [error] */
2506
+ $order_note = sprintf( esc_html__( '%1$s Payment Failed (%2$s)', 'woocommerce-square' ), $this->get_method_title(), $error_message );
2507
+
2508
+ // Mark order as failed if not already set, otherwise, make sure we add the order note so we can detect when someone fails to check out multiple times
2509
+ if ( ! $order->has_status( 'failed' ) ) {
2510
+ $order->update_status( 'failed', $order_note );
2511
+ } else {
2512
+ $order->add_order_note( $order_note );
2513
+ }
2514
+
2515
+ $this->add_debug_message( $error_message, 'error' );
2516
+
2517
+ // user message
2518
+ $user_message = '';
2519
+ if ( $response && $this->is_detailed_customer_decline_messages_enabled() ) {
2520
+ $user_message = $response->get_user_message();
2521
+ }
2522
+ if ( ! $user_message ) {
2523
+ $user_message = esc_html__( 'An error occurred, please try again or try an alternate form of payment.', 'woocommerce-square' );
2524
+ }
2525
+ Square_Helper::wc_add_notice( $user_message, 'error' );
2526
+ }
2527
+
2528
+ /** Customer ID Feature **************************************************/
2529
+
2530
+
2531
+ /**
2532
+ * Returns true if this is gateway that supports gateway customer IDs
2533
+ *
2534
+ * @since 3.0.0
2535
+ * @return boolean true if the gateway supports gateway customer IDs
2536
+ */
2537
+ public function supports_customer_id() {
2538
+
2539
+ return $this->supports( self::FEATURE_CUSTOMER_ID );
2540
+ }
2541
+
2542
+
2543
+ /**
2544
+ * Gets/sets the payment gateway customer id, this defaults to wc-{user id}
2545
+ * and retrieves/stores to the user meta named by get_customer_id_user_meta_name()
2546
+ * This can be overridden for gateways that use some other value, or made to
2547
+ * return false for gateways that don't support a customer id.
2548
+ *
2549
+ * @since 3.0.0
2550
+ * @see Payment_Gateway::get_customer_id_user_meta_name()
2551
+ * @param int $user_id wordpress user identifier
2552
+ * @param array $args optional additional arguments which can include: environment_id, autocreate (true/false), and order
2553
+ * @return string payment gateway customer id
2554
+ */
2555
+ public function get_customer_id( $user_id, $args = array() ) {
2556
+
2557
+ $defaults = array(
2558
+ 'environment_id' => $this->get_environment(),
2559
+ 'autocreate' => true,
2560
+ 'order' => null,
2561
+ );
2562
+
2563
+ $args = array_merge( $defaults, $args );
2564
+
2565
+ // does an id already exist for this user?
2566
+ $customer_id = get_user_meta( $user_id, $this->get_customer_id_user_meta_name( $args['environment_id'] ), true );
2567
+
2568
+ if ( ! $customer_id && $args['autocreate'] ) {
2569
+
2570
+ $billing_email = ( $args['order'] ) ? Order_Compatibility::get_prop( $args['order'], 'billing_email' ) : '';
2571
+
2572
+ // generate a new customer id. We try to use 'wc-<hash of billing email>'
2573
+ // if an order is available, on the theory that it will avoid clashing of
2574
+ // accounts if a customer uses the same merchant account on multiple independent
2575
+ // shops. Otherwise, we use 'wc-<user_id>-<random>'
2576
+ if ( $billing_email ) {
2577
+ $customer_id = 'wc-' . md5( $billing_email );
2578
+ } else {
2579
+ $customer_id = uniqid( 'wc-' . $user_id . '-' );
2580
+ }
2581
+
2582
+ $this->update_customer_id( $user_id, $customer_id, $args['environment_id'] );
2583
+ }
2584
+
2585
+ return $customer_id;
2586
+ }
2587
+
2588
+
2589
+ /**
2590
+ * Updates the payment gateway customer id for the given $environment, or
2591
+ * for the plugin current environment
2592
+ *
2593
+ * @since 3.0.0
2594
+ * @see Payment_Gateway::get_customer_id()
2595
+ * @param int $user_id WP user ID
2596
+ * @param string $customer_id payment gateway customer id
2597
+ * @param string $environment_id optional environment id, defaults to current environment
2598
+ * @return boolean|int false if no change was made (if the new value was the same as previous value) or if the update failed, meta id if the value was different and the update a success
2599
+ */
2600
+ public function update_customer_id( $user_id, $customer_id, $environment_id = null ) {
2601
+
2602
+ // default to current environment
2603
+ if ( is_null( $environment_id ) ) {
2604
+ $environment_id = $this->get_environment();
2605
+ }
2606
+
2607
+ return update_user_meta( $user_id, $this->get_customer_id_user_meta_name( $environment_id ), $customer_id );
2608
+ }
2609
+
2610
+
2611
+ /**
2612
+ * Removes the payment gateway customer id for the given $environment, or
2613
+ * for the plugin current environment
2614
+ *
2615
+ * @since 3.0.0
2616
+ * @param int $user_id WP user ID
2617
+ * @param string $environment_id optional environment id, defaults to current environment
2618
+ * @return boolean true on success, false on failure
2619
+ */
2620
+ public function remove_customer_id( $user_id, $environment_id = null ){
2621
+
2622
+ if ( is_null( $environment_id ) ) {
2623
+ $environment_id = $this->get_environment();
2624
+ }
2625
+
2626
+ // remove the user meta entry so it can be re-created
2627
+ return delete_user_meta( $user_id, $this->get_customer_id_user_meta_name( $environment_id ) );
2628
+ }
2629
+
2630
+
2631
+ /**
2632
+ * Returns a payment gateway customer id for a guest customer. This
2633
+ * defaults to wc-guest-{order id} but can be overridden for gateways that
2634
+ * use some other value, or made to return false for gateways that don't
2635
+ * support a customer id
2636
+ *
2637
+ * @since 3.0.0
2638
+ *
2639
+ * @param \WC_Order $order order object
2640
+ * @return string payment gateway guest customer id
2641
+ */
2642
+ public function get_guest_customer_id( \WC_Order $order ) {
2643
+
2644
+ // is there a customer id already tied to this order?
2645
+ $customer_id = $this->get_order_meta( Order_Compatibility::get_prop( $order, 'id' ), 'customer_id' );
2646
+
2647
+ if ( $customer_id ) {
2648
+ return $customer_id;
2649
+ }
2650
+
2651
+ // default
2652
+ return 'wc-guest-' . Order_Compatibility::get_prop( $order, 'id' );
2653
+ }
2654
+
2655
+
2656
+ /**
2657
+ * Returns the payment gateway customer id user meta name for persisting the
2658
+ * gateway customer id. Defaults to wc_{plugin id}_customer_id for the
2659
+ * production environment and wc_{plugin id}_customer_id_{environment}
2660
+ * for other environments. A particular environment can be passed,
2661
+ * otherwise this will default to the plugin current environment.
2662
+ *
2663
+ * This can be overridden and made to return false for gateways that don't
2664
+ * support a customer id.
2665
+ *
2666
+ * @since 3.0.0
2667
+ * @param string $environment_id optional environment id, defaults to plugin current environment
2668
+ * @return string payment gateway customer id user meta name
2669
+ */
2670
+ public function get_customer_id_user_meta_name( $environment_id = null ) {
2671
+
2672
+ if ( is_null( $environment_id ) ) {
2673
+ $environment_id = $this->get_environment();
2674
+ }
2675
+
2676
+ // no leading underscore since this is meant to be visible to the admin
2677
+ return 'wc_' . $this->get_plugin()->get_id() . '_customer_id' . ( ! $this->is_production_environment( $environment_id ) ? '_' . $environment_id : '' );
2678
+ }
2679
+
2680
+
2681
+ /** Authorization/Charge feature ******************************************/
2682
+
2683
+
2684
+ /**
2685
+ * Returns true if this is a credit card gateway which supports
2686
+ * authorization transactions
2687
+ *
2688
+ * @since 3.0.0
2689
+ * @return boolean true if the gateway supports authorization
2690
+ */
2691
+ public function supports_credit_card_authorization() {
2692
+ return $this->is_credit_card_gateway() && $this->supports( self::FEATURE_CREDIT_CARD_AUTHORIZATION );
2693
+ }
2694
+
2695
+
2696
+ /**
2697
+ * Returns true if this is a credit card gateway which supports
2698
+ * charge transactions
2699
+ *
2700
+ * @since 3.0.0
2701
+ * @return boolean true if the gateway supports charges
2702
+ */
2703
+ public function supports_credit_card_charge() {
2704
+ return $this->is_credit_card_gateway() && $this->supports( self::FEATURE_CREDIT_CARD_CHARGE );
2705
+ }
2706
+
2707
+
2708
+ /**
2709
+ * Determines if this is a credit card gateway that supports charging virtual-only orders.
2710
+ *
2711
+ * @since 3.0.0
2712
+ * @return bool
2713
+ */
2714
+ public function supports_credit_card_charge_virtual() {
2715
+ return $this->is_credit_card_gateway() && $this->supports( self::FEATURE_CREDIT_CARD_CHARGE_VIRTUAL );
2716
+ }
2717
+
2718
+
2719
+ /**
2720
+ * Returns true if the gateway supports capturing a charge
2721
+ *
2722
+ * @since 3.0.0
2723
+ * @return boolean true if the gateway supports capturing a charge
2724
+ */
2725
+ public function supports_credit_card_capture() {
2726
+ return $this->supports( self::FEATURE_CREDIT_CARD_CAPTURE );
2727
+ }
2728
+
2729
+
2730
+ /**
2731
+ * Determines if the gateway supports capturing a partial charge.
2732
+ *
2733
+ * @since 3.0.0
2734
+ *
2735
+ * @return bool
2736
+ */
2737
+ public function supports_credit_card_partial_capture() {
2738
+ return $this->supports_credit_card_capture() && $this->supports( self::FEATURE_CREDIT_CARD_PARTIAL_CAPTURE );
2739
+ }
2740
+
2741
+
2742
+ /**
2743
+ * Adds any credit card authorization/charge admin fields, allowing the
2744
+ * administrator to choose between performing authorizations or charges
2745
+ *
2746
+ * @since 3.0.0
2747
+ * @param array $form_fields gateway form fields
2748
+ * @return array $form_fields gateway form fields
2749
+ */
2750
+ protected function add_authorization_charge_form_fields( $form_fields ) {
2751
+
2752
+ assert( $this->supports_credit_card_authorization() && $this->supports_credit_card_charge() );
2753
+
2754
+ $form_fields['transaction_type'] = array(
2755
+ 'title' => esc_html__( 'Transaction Type', 'woocommerce-square' ),
2756
+ 'type' => 'select',
2757
+ 'desc_tip' => esc_html__( 'Select how transactions should be processed. Charge submits all transactions for settlement, Authorization simply authorizes the order total for capture later.', 'woocommerce-square' ),
2758
+ 'default' => self::TRANSACTION_TYPE_CHARGE,
2759
+ 'options' => array(
2760
+ self::TRANSACTION_TYPE_CHARGE => esc_html_x( 'Charge', 'noun, credit card transaction type', 'woocommerce-square' ),
2761
+ self::TRANSACTION_TYPE_AUTHORIZATION => esc_html_x( 'Authorization', 'credit card transaction type', 'woocommerce-square' ),
2762
+ ),
2763
+ );
2764
+
2765
+ if ( $this->supports_credit_card_charge_virtual() ) {
2766
+
2767
+ $form_fields['charge_virtual_orders'] = array(
2768
+ 'label' => esc_html__( 'Charge Virtual-Only Orders', 'woocommerce-square' ),
2769
+ 'type' => 'checkbox',
2770
+ 'description' => esc_html__( 'If the order contains exclusively virtual items, enable this to immediately charge, rather than authorize, the transaction.', 'woocommerce-square' ),
2771
+ 'default' => 'no',
2772
+ );
2773
+ }
2774
+
2775
+ if ( $this->supports_credit_card_partial_capture() ) {
2776
+
2777
+ $form_fields['enable_partial_capture'] = array(
2778
+ 'label' => esc_html__( 'Enable Partial Capture', 'woocommerce-square' ),
2779
+ 'type' => 'checkbox',
2780
+ 'description' => esc_html__( 'Allow orders to be partially captured multiple times.', 'woocommerce-square' ),
2781
+ 'default' => 'no',
2782
+ );
2783
+ }
2784
+
2785
+ if ( $this->supports_credit_card_capture() ) {
2786
+
2787
+ // get a list of the "paid" status names
2788
+ $paid_statuses = array_map( 'wc_get_order_status_name', (array) wc_get_is_paid_statuses() );
2789
+ $conjuction = _x( 'or', 'coordinating conjunction for a list of order statuses: on-hold, processing, or completed', 'woocommerce-square' );
2790
+
2791
+ $form_fields['enable_paid_capture'] = array(
2792
+ 'label' => __( 'Capture Paid Orders', 'woocommerce-square' ),
2793
+ 'type' => 'checkbox',
2794
+ 'description' => sprintf(
2795
+ esc_html__( 'Automatically capture orders when they are changed to %s.', 'woocommerce-square' ),
2796
+ esc_html( ! empty( $paid_statuses ) ? Square_Helper::list_array_items( $paid_statuses, $conjuction ) : __( 'a paid status', 'woocommerce-square' ) )
2797
+ ),
2798
+ 'default' => 'no',
2799
+ );
2800
+ }
2801
+
2802
+ return $form_fields;
2803
+ }
2804
+
2805
+
2806
+ /**
2807
+ * Return the authorization time window in hours. An authorization is considered
2808
+ * expired if it is older than this.
2809
+ *
2810
+ * 30 days (720 hours) is the standard authorization window. Individual gateways
2811
+ * can override this as necessary.
2812
+ *
2813
+ * @since 3.0.0
2814
+ * @return int hours
2815
+ */
2816
+ public function get_authorization_time_window() {
2817
+
2818
+ return 720;
2819
+ }
2820
+
2821
+
2822
+ /**
2823
+ * Determines if a credit card transaction should result in a charge.
2824
+ *
2825
+ * @since 3.0.0
2826
+ *
2827
+ * @param \WC_Order $order Optional. The order being charged
2828
+ * @return bool
2829
+ */
2830
+ public function perform_credit_card_charge( \WC_Order $order = null ) {
2831
+
2832
+ assert( $this->supports_credit_card_charge() );
2833
+
2834
+ $perform = self::TRANSACTION_TYPE_CHARGE === $this->transaction_type;
2835
+
2836
+ if ( ! $perform && $order && $this->supports_credit_card_charge_virtual() && 'yes' === $this->charge_virtual_orders ) {
2837
+ $perform = Square_Helper::is_order_virtual( $order );
2838
+ }
2839
+
2840
+ /**
2841
+ * Filters whether a credit card transaction should result in a charge.
2842
+ *
2843
+ * @since 3.0.0
2844
+ *
2845
+ * @param bool $perform whether the transaction should result in a charge
2846
+ * @param \WC_Order|null $order the order being charged
2847
+ * @param Payment_Gateway $gateway the gateway object
2848
+ */
2849
+ return apply_filters( 'wc_' . $this->get_id() . '_perform_credit_card_charge', $perform, $order, $this );
2850
+ }
2851
+
2852
+
2853
+ /**
2854
+ * Determines if a credit card transaction should result in an authorization.
2855
+ *
2856
+ * @since 3.0.0
2857
+ *
2858
+ * @param \WC_Order $order Optional. The order being authorized
2859
+ * @return bool
2860
+ */
2861
+ public function perform_credit_card_authorization( \WC_Order $order = null ) {
2862
+
2863
+ assert( $this->supports_credit_card_authorization() );
2864
+
2865
+ $perform = self::TRANSACTION_TYPE_AUTHORIZATION === $this->transaction_type && ! $this->perform_credit_card_charge( $order );
2866
+
2867
+ /**
2868
+ * Filters whether a credit card transaction should result in an authorization.
2869
+ *
2870
+ * @since 3.0.0
2871
+ * @param bool $perform whether the transaction should result in an authorization
2872
+ * @param \WC_Order|null $order the order being authorized
2873
+ * @param Payment_Gateway $gateway the gateway object
2874
+ */
2875
+ return apply_filters( 'wc_' . $this->get_id() . '_perform_credit_card_authorization', $perform, $order, $this );
2876
+ }
2877
+
2878
+
2879
+ /**
2880
+ * Determines if partial capture is enabled.
2881
+ *
2882
+ * @since 3.0.0
2883
+ *
2884
+ * @return bool
2885
+ */
2886
+ public function is_partial_capture_enabled() {
2887
+
2888
+ assert( $this->supports_credit_card_partial_capture() );
2889
+
2890
+ /**
2891
+ * Filters whether partial capture is enabled.
2892
+ *
2893
+ * @since 3.0.0
2894
+ *
2895
+ * @param bool $enabled whether partial capture is enabled
2896
+ * @param Payment_Gateway $gateway gateway object
2897
+ */
2898
+ return apply_filters( 'wc_' . $this->get_id() . '_partial_capture_enabled', 'yes' === $this->enable_partial_capture, $this );
2899
+ }
2900
+
2901
+
2902
+ /**
2903
+ * Determines if orders should be captured when switched to a "paid" status.
2904
+ *
2905
+ * @since 3.0.0
2906
+ *
2907
+ * @return bool
2908
+ */
2909
+ public function is_paid_capture_enabled() {
2910
+
2911
+ /**
2912
+ * Filters whether orders should be captured when switched to a "paid" status.
2913
+ *
2914
+ * @since 3.0.0
2915
+ *
2916
+ * @param bool $enabled whether "paid" capture is enabled
2917
+ * @param Payment_Gateway $gateway gateway object
2918
+ */
2919
+ return apply_filters( 'wc_' . $this->get_id() . '_paid_capture_enabled', 'yes' === $this->enable_paid_capture, $this );
2920
+ }
2921
+
2922
+
2923
+ /** Add Payment Method feature ********************************************/
2924
+
2925
+
2926
+ /**
2927
+ * Determines if the gateway supports the add payment method feature.
2928
+ *
2929
+ * @since 3.0.0
2930
+ *
2931
+ * @return bool
2932
+ */
2933
+ public function supports_add_payment_method() {
2934
+
2935
+ return $this->supports( self::FEATURE_ADD_PAYMENT_METHOD );
2936
+ }
2937
+
2938
+
2939
+ // TODO: generalize the direct methods
2940
+
2941
+
2942
+ /** Card Types feature ******************************************************/
2943
+
2944
+
2945
+ /**
2946
+ * Returns true if the gateway supports card_types: allows the admin to
2947
+ * configure card type icons to display at checkout
2948
+ *
2949
+ * @since 3.0.0
2950
+ * @return boolean true if the gateway supports card_types
2951
+ */
2952
+ public function supports_card_types() {
2953
+ return $this->is_credit_card_gateway() && $this->supports( self::FEATURE_CARD_TYPES );
2954
+ }
2955
+
2956
+
2957
+ /**
2958
+ * Returns the array of accepted card types if this is a credit card gateway
2959
+ * that supports card types. Return format is 'VISA', 'MC', 'AMEX', etc
2960
+ *
2961
+ * @since 3.0.0
2962
+ * @see get_available_card_types()
2963
+ * @return array of accepted card types, ie 'VISA', 'MC', 'AMEX', etc
2964
+ */
2965
+ public function get_card_types() {
2966
+
2967
+ assert( $this->supports_card_types() );
2968
+
2969
+ return $this->card_types;
2970
+ }
2971
+
2972
+
2973
+ /**
2974
+ * Adds any card types form fields, allowing the admin to configure the card
2975
+ * types icons displayed during checkout
2976
+ *
2977
+ * @since 3.0.0
2978
+ * @param array $form_fields gateway form fields
2979
+ * @return array $form_fields gateway form fields
2980
+ */
2981
+ protected function add_card_types_form_fields( $form_fields ) {
2982
+
2983
+ assert( $this->supports_card_types() );
2984
+
2985
+ $form_fields['card_types'] = array(
2986
+ 'title' => esc_html__( 'Accepted Card Logos', 'woocommerce-square' ),
2987
+ 'type' => 'multiselect',
2988
+ 'desc_tip' => __( 'These are the card logos that are displayed to customers as accepted during checkout.', 'woocommerce-square' ),
2989
+ 'description' => sprintf(
2990
+ /* translators: Placeholders: %1$s - <strong> tag, %2$s - </strong> tag */
2991
+ __( 'This setting %1$sdoes not%2$s change which card types the gateway will accept. Accepted cards are configured from your payment processor account.', 'woocommerce-square' ),
2992
+ '<strong>',
2993
+ '</strong>'
2994
+ ),
2995
+ 'default' => array_keys( $this->get_available_card_types() ),
2996
+ 'class' => 'wc-enhanced-select',
2997
+ 'css' => 'width: 350px;',
2998
+ 'options' => $this->get_available_card_types(),
2999
+ );
3000
+
3001
+ return $form_fields;
3002
+ }
3003
+
3004
+
3005
+ /**
3006
+ * Returns available card types, ie 'VISA' => 'Visa', 'MC' => 'MasterCard', etc
3007
+ *
3008
+ * @since 3.0.0
3009
+ * @return array associative array of card type to display name
3010
+ */
3011
+ public function get_available_card_types() {
3012
+
3013
+ assert( $this->supports_card_types() );
3014
+
3015
+ // default available card types
3016
+ if ( ! isset( $this->available_card_types ) ) {
3017
+
3018
+ $this->available_card_types = array(
3019
+ 'VISA' => esc_html_x( 'Visa', 'credit card type', 'woocommerce-square' ),
3020
+ 'MC' => esc_html_x( 'MasterCard', 'credit card type', 'woocommerce-square' ),
3021
+ 'AMEX' => esc_html_x( 'American Express', 'credit card type', 'woocommerce-square' ),
3022
+ 'DISC' => esc_html_x( 'Discover', 'credit card type', 'woocommerce-square' ),
3023
+ 'DINERS' => esc_html_x( 'Diners', 'credit card type', 'woocommerce-square' ),
3024
+ 'JCB' => esc_html_x( 'JCB', 'credit card type', 'woocommerce-square' ),
3025
+ );
3026
+
3027
+ }
3028
+
3029
+ /**
3030
+ * Payment Gateway Available Card Types Filter.
3031
+ *
3032
+ * Allow actors to modify the available card types.
3033
+ *
3034
+ * @since 3.0.0
3035
+ * @param array $available_card_types
3036
+ */
3037
+ return apply_filters( 'wc_' . $this->get_id() . '_available_card_types', $this->available_card_types );
3038
+ }
3039
+
3040
+
3041
+ /** Tokenization feature **************************************************/
3042
+
3043
+
3044
+ /**
3045
+ * Returns true if the gateway supports tokenization
3046
+ *
3047
+ * @since 3.0.0
3048
+ * @return boolean true if the gateway supports tokenization
3049
+ */
3050
+ public function supports_tokenization() {
3051
+ return $this->supports( self::FEATURE_TOKENIZATION );
3052
+ }
3053
+
3054
+
3055
+ /**
3056
+ * Returns true if tokenization is enabled
3057
+ *
3058
+ * @since 3.0.0
3059
+ * @return boolean true if tokenization is enabled
3060
+ */
3061
+ public function tokenization_enabled() {
3062
+
3063
+ assert( $this->supports_tokenization() );
3064
+
3065
+ return 'yes' == $this->tokenization;
3066
+ }
3067
+
3068
+
3069
+ /**
3070
+ * Adds any tokenization form fields for the settings page
3071
+ *
3072
+ * @since 3.0.0
3073
+ * @param array $form_fields gateway form fields
3074
+ * @return array $form_fields gateway form fields
3075
+ */
3076
+ protected function add_tokenization_form_fields( $form_fields ) {
3077
+
3078
+ assert( $this->supports_tokenization() );
3079
+
3080
+ $form_fields['tokenization'] = array(
3081
+ /* translators: http://www.cybersource.com/products/payment_security/payment_tokenization/ and https://en.wikipedia.org/wiki/Tokenization_(data_security) */
3082
+ 'title' => esc_html__( 'Tokenization', 'woocommerce-square' ),
3083
+ 'label' => esc_html__( 'Allow customers to securely save their payment details for future checkout.', 'woocommerce-square' ),
3084
+ 'type' => 'checkbox',
3085
+ 'default' => 'no',
3086
+ );
3087
+
3088
+ return $form_fields;
3089
+ }
3090
+
3091
+ /**
3092
+ * Safely get and trim data from $_REQUEST
3093
+ *
3094
+ * @since 3.0.0
3095
+ * @param string $key array key to get from $_REQUEST array
3096
+ * @return string value from $_REQUEST or blank string if $_REQUEST[ $key ] is not set
3097
+ */
3098
+ protected function get_request( $key ) {
3099
+
3100
+ if ( isset( $_REQUEST[ $key ] ) ) {
3101
+ return trim( $_REQUEST[ $key ] );
3102
+ }
3103
+
3104
+ return '';
3105
+ }
3106
+
3107
+
3108
+ /**
3109
+ * Add API request logging for the gateway. The main plugin class typically handles this, but the payment
3110
+ * gateway plugin class no-ops the method so each gateway's requests can be logged individually (e.g. credit card)
3111
+ * and make use of the payment gateway-specific add_debug_message() method
3112
+ *
3113
+ * @since 3.0.0
3114
+ * @see Plugin::add_api_request_logging()
3115
+ */
3116
+ public function add_api_request_logging() {
3117
+
3118
+ if ( ! has_action( 'wc_' . $this->get_id() . '_api_request_performed' ) ) {
3119
+ add_action( 'wc_' . $this->get_id() . '_api_request_performed', array( $this, 'log_api_request' ), 10, 2 );
3120
+ }
3121
+ }
3122
+
3123
+
3124
+ /**
3125
+ * Log gateway API requests/responses
3126
+ *
3127
+ * @since 3.0.0
3128
+ * @param array $request request data, see Base::broadcast_request() for format
3129
+ * @param array $response response data
3130
+ */
3131
+ public function log_api_request( $request, $response ) {
3132
+
3133
+ // request
3134
+ $this->add_debug_message( $this->get_plugin()->get_api_log_message( $request ), 'message' );
3135
+
3136
+ // response
3137
+ if ( ! empty( $response ) ) {
3138
+ $this->add_debug_message( $this->get_plugin()->get_api_log_message( $response ), 'message' );
3139
+ }
3140
+ }
3141
+
3142
+
3143
+ /**
3144
+ * Adds debug messages to the page as a WC message/error, and/or to the WC Error log
3145
+ *
3146
+ * @since 3.0.0
3147
+ * @param string $message message to add
3148
+ * @param string $type how to add the message, options are:
3149
+ * 'message' (styled as WC message), 'error' (styled as WC Error)
3150
+ */
3151
+ public function add_debug_message( $message, $type = 'message' ) {
3152
+
3153
+ // do nothing when debug mode is off or no message
3154
+ if ( 'off' == $this->debug_off() || ! $message ) {
3155
+ return;
3156
+ }
3157
+
3158
+ // add log message to WC logger if log/both is enabled
3159
+ if ( $this->debug_log() ) {
3160
+ $this->get_plugin()->log( $message, $this->get_id() );
3161
+ }
3162
+
3163
+ // avoid adding notices when performing refunds, these occur in the admin as an Ajax call, so checking the current filter
3164
+ // is the only reliably way to do so
3165
+ if ( in_array( 'wp_ajax_woocommerce_refund_line_items', $GLOBALS['wp_current_filter'], true ) ) {
3166
+ return;
3167
+ }
3168
+
3169
+ // add debug message to woocommerce->errors/messages if checkout or both is enabled, the admin/Ajax check ensures capture charge transactions aren't logged as notices to the front end
3170
+ if ( ( $this->debug_checkout() || ( 'error' === $type && $this->is_test_environment() ) ) && ( ! is_admin() || wp_doing_ajax() ) ) {
3171
+
3172
+ if ( 'message' === $type ) {
3173
+
3174
+ Square_Helper::wc_add_notice( str_replace( "\n", "<br/>", htmlspecialchars( $message ) ), 'notice' );
3175
+
3176
+ } else {
3177
+
3178
+ // defaults to error message
3179
+ Square_Helper::wc_add_notice( str_replace( "\n", "<br/>", htmlspecialchars( $message ) ), 'error' );
3180
+ }
3181
+ }
3182
+ }
3183
+
3184
+
3185
+ /**
3186
+ * Get payment currency, either from current order or WC settings
3187
+ *
3188
+ * @since 3.0.0
3189
+ * @return string three-letter currency code
3190
+ */
3191
+ protected function get_payment_currency() {
3192
+
3193
+ $currency = get_woocommerce_currency();
3194
+ $order_id = $this->get_checkout_pay_page_order_id();
3195
+
3196
+ // Gets currency for the current order, that is about to be paid for
3197
+ if ( $order_id ) {
3198
+
3199
+ $order = wc_get_order( $order_id );
3200
+ $currency = Order_Compatibility::get_prop( $order, 'currency', 'view' );
3201
+ }
3202
+
3203
+ return $currency;
3204
+ }
3205
+
3206
+
3207
+ /**
3208
+ * Returns true if $currency is accepted by this gateway
3209
+ *
3210
+ * @since 3.0.0
3211
+ * @param string $currency optional three-letter currency code, defaults to
3212
+ * order currency (if available) or currently configured WooCommerce
3213
+ * currency
3214
+ * @return boolean true if $currency is accepted, false otherwise
3215
+ */
3216
+ public function currency_is_accepted( $currency = null ) {
3217
+
3218
+ // accept all currencies
3219
+ if ( ! $this->currencies ) {
3220
+ return true;
3221
+ }
3222
+
3223
+ // default to order/WC currency
3224
+ if ( is_null( $currency ) ) {
3225
+ $currency = $this->get_payment_currency();
3226
+ }
3227
+
3228
+ return in_array( $currency, $this->currencies, true );
3229
+ }
3230
+
3231
+ /**
3232
+ * Adds order meta data.
3233
+ *
3234
+ * @since 3.0.0
3235
+ *
3236
+ * @param \WC_Order|int the order to add meta to
3237
+ * @param string $key meta key (already prefixed with gateway ID)
3238
+ * @param mixed $value meta value
3239
+ * @param bool $unique whether the meta value should be unique
3240
+ * @return false|void
3241
+ */
3242
+ public function add_order_meta( $order, $key, $value, $unique = false ) {
3243
+
3244
+ if ( is_numeric( $order ) ) {
3245
+ $order = wc_get_order( $order );
3246
+ }
3247
+
3248
+ if ( ! $order instanceof \WC_Order ) {
3249
+ return false;
3250
+ }
3251
+
3252
+ return Order_Compatibility::add_meta_data( $order, $this->get_order_meta_prefix() . $key, $value, $unique );
3253
+ }
3254
+
3255
+
3256
+ /**
3257
+ * Gets order meta data.
3258
+ *
3259
+ * Note this is hardcoded to return a single value for the get_post_meta() call.
3260
+ *
3261
+ * @since 3.0.0
3262
+ * @param \WC_Order|int the order to get meta for
3263
+ * @param string $key meta key
3264
+ * @return mixed
3265
+ */
3266
+ public function get_order_meta( $order, $key ) {
3267
+
3268
+ if ( is_numeric( $order ) ) {
3269
+ $order = wc_get_order( $order );
3270
+ }
3271
+
3272
+ if ( ! $order instanceof \WC_Order ) {
3273
+ return false;
3274
+ }
3275
+
3276
+ return Order_Compatibility::get_meta( $order, $this->get_order_meta_prefix() . $key, true );
3277
+ }
3278
+
3279
+
3280
+ /**
3281
+ * Updates order meta data.
3282
+ *
3283
+ * @since 3.0.0
3284
+ *
3285
+ * @param \WC_Order|int the order to update meta for
3286
+ * @param string $key meta key
3287
+ * @param mixed $value meta value
3288
+ * @return false|void
3289
+ */
3290
+ public function update_order_meta( $order, $key, $value ) {
3291
+
3292
+ if ( is_numeric( $order ) ) {
3293
+ $order = wc_get_order( $order );
3294
+ }
3295
+
3296
+ if ( ! $order instanceof \WC_Order ) {
3297
+ return false;
3298
+ }
3299
+
3300
+ return Order_Compatibility::update_meta_data( $order, $this->get_order_meta_prefix() . $key, $value );
3301
+ }
3302
+
3303
+
3304
+ /**
3305
+ * Delete order meta data.
3306
+ *
3307
+ * @since 3.0.0
3308
+ * @param \WC_Order|int the order to delete meta for
3309
+ * @param string $key meta key
3310
+ * @return bool
3311
+ */
3312
+ public function delete_order_meta( $order, $key ) {
3313
+
3314
+ if ( is_numeric( $order ) ) {
3315
+ $order = wc_get_order( $order );
3316
+ }
3317
+
3318
+ if ( ! $order instanceof \WC_Order ) {
3319
+ return false;
3320
+ }
3321
+
3322
+ return Order_Compatibility::delete_meta_data( $order, $this->get_order_meta_prefix() . $key );
3323
+ }
3324
+
3325
+
3326
+ /**
3327
+ * Gets the order meta prefixed used for the *_order_meta() methods
3328
+ *
3329
+ * Defaults to `_wc_{gateway_id}_`
3330
+ *
3331
+ * @since 3.0.0
3332
+ * @return string
3333
+ */
3334
+ public function get_order_meta_prefix() {
3335
+ return '_wc_' . $this->get_id() . '_';
3336
+ }
3337
+
3338
+ /**
3339
+ * Returns the payment gateway id
3340
+ *
3341
+ * @since 3.0.0
3342
+ * @see WC_Payment_Gateway::$id
3343
+ * @return string payment gateway id
3344
+ */
3345
+ public function get_id() {
3346
+ return $this->id;
3347
+ }
3348
+
3349
+ /**
3350
+ * Returns the payment gateway id with dashes in place of underscores, and
3351
+ * appropriate for use in frontend element names, classes and ids
3352
+ *
3353
+ * @since 3.0.0
3354
+ * @return string payment gateway id with dashes in place of underscores
3355
+ */
3356
+ public function get_id_dasherized() {
3357
+ return str_replace( '_', '-', $this->get_id() );
3358
+ }
3359
+
3360
+
3361
+ /**
3362
+ * Returns the parent plugin object
3363
+ *
3364
+ * @since 3.0.0
3365
+ *
3366
+ * @return Payment_Gateway_Plugin the parent plugin object
3367
+ */
3368
+ public function get_plugin() {
3369
+
3370
+ return $this->plugin;
3371
+ }
3372
+
3373
+
3374
+ /**
3375
+ * Returns the admin method title. This should be the gateway name, ie
3376
+ * 'Intuit QBMS'
3377
+ *
3378
+ * @since 3.0.0
3379
+ * @see WC_Settings_API::$method_title
3380
+ * @return string method title
3381
+ */
3382
+ public function get_method_title() {
3383
+ return $this->method_title;
3384
+ }
3385
+
3386
+
3387
+ /**
3388
+ * Determines if the Card Security Code (CVV) field should be used at checkout.
3389
+ *
3390
+ * @since 3.0.0
3391
+ * @return bool
3392
+ */
3393
+ public function csc_enabled() {
3394
+ return 'yes' === $this->enable_csc;
3395
+ }
3396
+
3397
+
3398
+ /**
3399
+ * Determines if the Card Security Code (CVV) field should be used for saved cards at checkout.
3400
+ *
3401
+ * @since 3.0.0
3402
+ * @return bool
3403
+ */
3404
+ public function csc_enabled_for_tokens() {
3405
+ return $this->csc_enabled() && 'yes' === $this->enable_token_csc;
3406
+ }
3407
+
3408
+
3409
+ /**
3410
+ * Determines if the Card Security Code (CVV) field should be required at checkout.
3411
+ *
3412
+ * @since 3.0.0
3413
+ * @return bool
3414
+ */
3415
+ public function csc_required() {
3416
+ return $this->csc_enabled();
3417
+ }
3418
+
3419
+
3420
+ /**
3421
+ * Determines if the gateway supports sharing settings with sibling gateways.
3422
+ *
3423
+ * @since 3.0.0
3424
+ * @return bool
3425
+ */
3426
+ public function share_settings() {
3427
+ return true;
3428
+ }
3429
+
3430
+
3431
+ /**
3432
+ * Determines if settings should be inherited for this gateway.
3433
+ *
3434
+ * @since 3.0.0
3435
+ * @return bool
3436
+ */
3437
+ public function inherit_settings() {
3438
+ return 'yes' === $this->inherit_settings;
3439
+ }
3440
+
3441
+ /**
3442
+ * Returns an array of two-letter country codes this gateway is allowed for, defaults to all
3443
+ *
3444
+ * @since 3.0.0
3445
+ * @see WC_Payment_Gateway::$countries
3446
+ * @return array of two-letter country codes this gateway is allowed for, defaults to all
3447
+ */
3448
+ public function get_available_countries() {
3449
+ return $this->countries;
3450
+ }
3451
+
3452
+ /**
3453
+ * Add support for the named feature or features
3454
+ *
3455
+ * @since 3.0.0
3456
+ * @param string|array $feature the feature name or names supported by this gateway
3457
+ */
3458
+ public function add_support( $feature ) {
3459
+
3460
+ if ( ! is_array( $feature ) ) {
3461
+ $feature = array( $feature );
3462
+ }
3463
+
3464
+ foreach ( $feature as $name ) {
3465
+
3466
+ // add support for feature if it's not already declared
3467
+ if ( ! in_array( $name, $this->supports, true ) ) {
3468
+
3469
+ $this->supports[] = $name;
3470
+
3471
+ /**
3472
+ * Payment Gateway Add Support Action.
3473
+ *
3474
+ * Fired when declaring support for a specific gateway feature. Allows other actors
3475
+ * (including ourselves) to take action when support is declared.
3476
+ *
3477
+ * @since 3.0.0
3478
+ *
3479
+ * @param Payment_Gateway $this instance
3480
+ * @param string $name of supported feature being added
3481
+ */
3482
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_supports_' . str_replace( '-', '_', $name ), $this, $name );
3483
+ }
3484
+
3485
+ }
3486
+ }
3487
+
3488
+ /**
3489
+ * Set all features supported
3490
+ *
3491
+ * @since 3.0.0
3492
+ * @param array $features array of supported feature names
3493
+ */
3494
+ public function set_supports( $features ) {
3495
+ $this->supports = $features;
3496
+ }
3497
+
3498
+ /**
3499
+ * Gets the set of environments supported by this gateway. All gateways
3500
+ * support at least the production environment
3501
+ *
3502
+ * @since 3.0.0
3503
+ * @return array associative array of environment id to name supported by this gateway
3504
+ */
3505
+ public function get_environments() {
3506
+
3507
+ // default set of environments consists of 'production'
3508
+ if ( ! isset( $this->environments ) ) {
3509
+ $this->environments = array( self::ENVIRONMENT_PRODUCTION => esc_html_x( 'Production', 'software environment', 'woocommerce-square' ) );
3510
+ }
3511
+
3512
+ return $this->environments;
3513
+ }
3514
+
3515
+
3516
+ /**
3517
+ * Returns the environment setting, one of the $environments keys, ie
3518
+ * 'production'
3519
+ *
3520
+ * @since 3.0.0
3521
+ * @return string the configured environment id
3522
+ */
3523
+ public function get_environment() {
3524
+ return $this->environment;
3525
+ }
3526
+
3527
+
3528
+ /**
3529
+ * Get the configured environment's display name.
3530
+ *
3531
+ * @since 3.0.0
3532
+ * @return string The configured environment name
3533
+ */
3534
+ public function get_environment_name() {
3535
+
3536
+ $environments = $this->get_environments();
3537
+
3538
+ $environment_id = $this->get_environment();
3539
+ $environment_name = ( isset( $environments[ $environment_id ] ) ) ? $environments[ $environment_id ] : $environment_id;
3540
+
3541
+ return $environment_name;
3542
+ }
3543
+
3544
+
3545
+ /**
3546
+ * Returns true if the current environment is $environment_id.
3547
+ *
3548
+ * @since 3.0.0
3549
+ *
3550
+ * @param string|mixed $environment_id
3551
+ * @return bool
3552
+ */
3553
+ public function is_environment( $environment_id ) {
3554
+ return $environment_id == $this->get_environment();
3555
+ }
3556
+
3557
+
3558
+ /**
3559
+ * Returns true if the current gateway environment is configured to
3560
+ * 'production'. All gateways have at least the production environment
3561
+ *
3562
+ * @since 3.0.0
3563
+ * @param string $environment_id optional environment id to check, otherwise defaults to the gateway current environment
3564
+ * @return boolean true if $environment_id (if non-null) or otherwise the current environment is production
3565
+ */
3566
+ public function is_production_environment( $environment_id = null ) {
3567
+
3568
+ // if an environment was passed in, see whether it's the production environment
3569
+ if ( ! is_null( $environment_id ) ) {
3570
+ return self::ENVIRONMENT_PRODUCTION == $environment_id;
3571
+ }
3572
+
3573
+ // default: check the current environment
3574
+ return $this->is_environment( self::ENVIRONMENT_PRODUCTION );
3575
+ }
3576
+
3577
+
3578
+ /**
3579
+ * Returns true if the current gateway environment is configured to 'test'
3580
+ *
3581
+ * @since 3.0.0
3582
+ * @param string $environment_id optional environment id to check, otherwise defaults to the gateway current environment
3583
+ * @return boolean true if $environment_id (if non-null) or otherwise the current environment is test
3584
+ */
3585
+ public function is_test_environment( $environment_id = null ) {
3586
+
3587
+ // if an environment was passed in, see whether it's the production environment
3588
+ if ( ! is_null( $environment_id ) ) {
3589
+ return self::ENVIRONMENT_TEST == $environment_id;
3590
+ }
3591
+
3592
+ // default: check the current environment
3593
+ return $this->is_environment( self::ENVIRONMENT_TEST );
3594
+ }
3595
+
3596
+
3597
+ /**
3598
+ * Returns true if the gateway is enabled. This has nothing to do with
3599
+ * whether the gateway is properly configured or functional.
3600
+ *
3601
+ * @since 3.0.0
3602
+ * @see WC_Payment_Gateway::$enabled
3603
+ * @return boolean true if the gateway is enabled
3604
+ */
3605
+ public function is_enabled() {
3606
+ return 'yes' == $this->enabled;
3607
+ }
3608
+
3609
+
3610
+ /**
3611
+ * Returns true if detailed decline messages should be displayed to
3612
+ * customers on checkout when available, rather than a single generic
3613
+ * decline message
3614
+ *
3615
+ * @since 3.0.0
3616
+ * @see Payment_Gateway_API_Response_Message_Helper
3617
+ * @see Payment_Gateway_API_Response::get_user_message()
3618
+ * @return boolean true if detailed decline messages should be displayed
3619
+ * on checkout
3620
+ */
3621
+ public function is_detailed_customer_decline_messages_enabled() {
3622
+ return 'yes' == $this->enable_customer_decline_messages;
3623
+ }
3624
+
3625
+
3626
+ /**
3627
+ * Returns the set of accepted currencies, or empty array if all currencies
3628
+ * are accepted by this gateway
3629
+ *
3630
+ * @since 3.0.0
3631
+ * @return array of currencies accepted by this gateway
3632
+ */
3633
+ public function get_accepted_currencies() {
3634
+ return $this->currencies;
3635
+ }
3636
+
3637
+
3638
+ /**
3639
+ * Returns true if all debugging is disabled
3640
+ *
3641
+ * @since 3.0.0
3642
+ * @return boolean if all debuging is disabled
3643
+ */
3644
+ public function debug_off() {
3645
+ return self::DEBUG_MODE_OFF === $this->debug_mode;
3646
+ }
3647
+
3648
+
3649
+ /**
3650
+ * Returns true if debug logging is enabled
3651
+ *
3652
+ * @since 3.0.0
3653
+ * @return boolean if debug logging is enabled
3654
+ */
3655
+ public function debug_log() {
3656
+ return self::DEBUG_MODE_LOG === $this->debug_mode || self::DEBUG_MODE_BOTH === $this->debug_mode;
3657
+ }
3658
+
3659
+
3660
+ /**
3661
+ * Returns true if checkout debugging is enabled. This will cause debugging
3662
+ * statements to be displayed on the checkout/pay pages
3663
+ *
3664
+ * @since 3.0.0
3665
+ * @return boolean if checkout debugging is enabled
3666
+ */
3667
+ public function debug_checkout() {
3668
+ return self::DEBUG_MODE_CHECKOUT === $this->debug_mode || self::DEBUG_MODE_BOTH === $this->debug_mode;
3669
+ }
3670
+
3671
+
3672
+ /**
3673
+ * Returns true if this is a direct type gateway
3674
+ *
3675
+ * @since 3.0.0
3676
+ * @return boolean if this is a direct payment gateway
3677
+ */
3678
+ public function is_direct_gateway() {
3679
+ return false;
3680
+ }
3681
+
3682
+
3683
+ /**
3684
+ * Returns true if this is a hosted type gateway
3685
+ *
3686
+ * @since 3.0.0
3687
+ * @return boolean if this is a hosted IPN payment gateway
3688
+ */
3689
+ public function is_hosted_gateway() {
3690
+ return false;
3691
+ }
3692
+
3693
+
3694
+ /**
3695
+ * Returns the payment type for this gateway
3696
+ *
3697
+ * @since 3.0.0
3698
+ * @return string the payment type, ie 'credit-card'.
3699
+ */
3700
+ public function get_payment_type() {
3701
+ return $this->payment_type;
3702
+ }
3703
+
3704
+
3705
+ /**
3706
+ * Returns true if this is a credit card gateway
3707
+ *
3708
+ * @since 3.0.0
3709
+ * @return boolean true if this is a credit card gateway
3710
+ */
3711
+ public function is_credit_card_gateway() {
3712
+ return self::PAYMENT_TYPE_CREDIT_CARD == $this->get_payment_type();
3713
+ }
3714
+
3715
+ /**
3716
+ * Returns the API instance for this gateway if it uses direct communication
3717
+ *
3718
+ * This is a stub method which must be overridden if this gateway performs
3719
+ * direct communication
3720
+ *
3721
+ * @since 3.0.0
3722
+ * @return SquareFramework\PaymentGateway\Api\Payment_Gateway_API the payment gateway API instance
3723
+ */
3724
+ public function get_api() {
3725
+
3726
+ // concrete stub method
3727
+ assert( false );
3728
+ }
3729
+
3730
+
3731
+ /**
3732
+ * Returns the order_id if on the checkout pay page
3733
+ *
3734
+ * @since 3.0.0
3735
+ * @return int order identifier
3736
+ */
3737
+ public function get_checkout_pay_page_order_id() {
3738
+ global $wp;
3739
+
3740
+ return isset( $wp->query_vars['order-pay'] ) ? absint( $wp->query_vars['order-pay'] ) : 0;
3741
+ }
3742
+
3743
+ /**
3744
+ * Gets the maximum amount that can be captured from an order.
3745
+ *
3746
+ * Gateways can override this for an value above or below the order total.
3747
+ * For instance, some processors allow capturing an amount a certain
3748
+ * percentage higher than the payment total.
3749
+ *
3750
+ * @since 3.0.0
3751
+ *
3752
+ * @param \WC_Order $order order object
3753
+ * @return float
3754
+ */
3755
+ public function get_order_capture_maximum( \WC_Order $order ) {
3756
+
3757
+ wc_deprecated_function( __METHOD__, '3.0.0', get_class( $this->get_capture_handler() ) . '::get_order_capture_maximum()' );
3758
+
3759
+ return $this->get_capture_handler()->get_order_capture_maximum( $order );
3760
+ }
3761
+
3762
+
3763
+ /**
3764
+ * Gets the amount originally authorized for an order.
3765
+ *
3766
+ * @since 3.0.0
3767
+ *
3768
+ * @param \WC_Order $order order object
3769
+ * @return float
3770
+ */
3771
+ public function get_order_authorization_amount( \WC_Order $order ) {
3772
+
3773
+ wc_deprecated_function( __METHOD__, '3.0.0', get_class( $this->get_capture_handler() ) . '::get_order_authorization_amount()' );
3774
+
3775
+ return $this->get_capture_handler()->get_order_authorization_amount( $order );
3776
+ }
3777
+
3778
+ /**
3779
+ * Returns the gateway icon markup
3780
+ *
3781
+ * @since 3.0.0
3782
+ * @see WC_Payment_Gateway::get_icon()
3783
+ * @return string icon markup
3784
+ */
3785
+ public function get_icon() {
3786
+
3787
+ $icon = '';
3788
+
3789
+ // specific icon
3790
+ if ( $this->icon ) {
3791
+
3792
+ // use icon provided by filter
3793
+ $icon = sprintf( '<img src="%s" alt="%s" class="sv-wc-payment-gateway-icon wc-%s-payment-gateway-icon" />', esc_url( \WC_HTTPS::force_https_url( $this->icon ) ), esc_attr( $this->get_title() ), esc_attr( $this->get_id_dasherized() ) );
3794
+ }
3795
+
3796
+ // credit card images
3797
+ if ( ! $icon && $this->supports_card_types() && $this->get_card_types() ) {
3798
+
3799
+ // display icons for the selected card types
3800
+ foreach ( $this->get_card_types() as $card_type ) {
3801
+
3802
+ $card_type = Payment_Gateway_Helper::normalize_card_type( $card_type );
3803
+
3804
+ if ( $url = $this->get_payment_method_image_url( $card_type ) ) {
3805
+ $icon .= sprintf( '<img src="%s" alt="%s" class="sv-wc-payment-gateway-icon wc-%s-payment-gateway-icon" width="40" height="25" style="width: 40px; height: 25px;" />', esc_url( $url ), esc_attr( $card_type ), esc_attr( $this->get_id_dasherized() ) );
3806
+ }
3807
+ }
3808
+ }
3809
+
3810
+ /* This filter is documented in WC core */
3811
+ return apply_filters( 'woocommerce_gateway_icon', $icon, $this->get_id() );
3812
+ }
3813
+ }
includes/Framework/PaymentGateway/Payment_Gateway_Direct.php ADDED
@@ -0,0 +1,1007 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway;
4
+
5
+ use WooCommerce;
6
+ use WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Helper;
7
+ use WooCommerce\Square\Framework\Square_Helper;
8
+ use WooCommerce\Square\Framework\Compatibility\Order_Compatibility;
9
+ use WooCommerce\Square\Framework\Addresses\Customer_Address;
10
+ use WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Response_Interface;
11
+
12
+ defined( 'ABSPATH' ) or exit;
13
+
14
+ /**
15
+ * # WooCommerce Payment Gateway Framework Direct Gateway
16
+ *
17
+ * @since 3.0.0
18
+ */
19
+ abstract class Payment_Gateway_Direct extends Payment_Gateway {
20
+
21
+ /**
22
+ * Validate the payment fields when processing the checkout
23
+ *
24
+ * NOTE: if we want to bring billing field validation (ie length) into the
25
+ * fold, see the Elavon VM Payment Gateway for a sample implementation
26
+ *
27
+ * @since 3.0.0
28
+ * @see WC_Payment_Gateway::validate_fields()
29
+ * @return bool true if fields are valid, false otherwise
30
+ */
31
+ public function validate_fields() {
32
+
33
+ $is_valid = parent::validate_fields();
34
+
35
+ if ( $this->supports_tokenization() ) {
36
+
37
+ // tokenized transaction?
38
+ if ( Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) {
39
+
40
+ // unknown token?
41
+ if ( ! $this->get_payment_tokens_handler()->user_has_token( get_current_user_id(), Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) ) {
42
+ Square_Helper::wc_add_notice( esc_html__( 'Payment error, please try another payment method or contact us to complete your transaction.', 'woocommerce-square' ), 'error' );
43
+ $is_valid = false;
44
+ }
45
+
46
+ // Check the CSC if enabled
47
+ if ( $this->is_credit_card_gateway() && $this->csc_enabled_for_tokens() ) {
48
+ $is_valid = $this->validate_csc( Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-csc' ) ) && $is_valid;
49
+ }
50
+
51
+ // no more validation to perform
52
+ return $is_valid;
53
+ }
54
+ }
55
+
56
+ // validate remaining payment fields
57
+ if ( $this->is_credit_card_gateway() ) {
58
+ return $this->validate_credit_card_fields( $is_valid );
59
+ } else {
60
+ $method_name = 'validate_' . str_replace( '-', '_', strtolower( $this->get_payment_type() ) ) . '_fields';
61
+ if ( is_callable( array( $this, $method_name ) ) ) {
62
+ return $this->$method_name( $is_valid );
63
+ }
64
+ }
65
+
66
+ // no more validation to perform. Return the parent method's outcome.
67
+ return $is_valid;
68
+ }
69
+
70
+
71
+ /**
72
+ * Returns true if the posted credit card fields are valid, false otherwise
73
+ *
74
+ * @since 3.0.0
75
+ * @param boolean $is_valid true if the fields are valid, false otherwise
76
+ * @return boolean true if the fields are valid, false otherwise
77
+ */
78
+ protected function validate_credit_card_fields( $is_valid ) {
79
+
80
+ $account_number = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-account-number' );
81
+ $expiration_month = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-exp-month' );
82
+ $expiration_year = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-exp-year' );
83
+ $expiry = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-expiry' );
84
+ $csc = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-csc' );
85
+
86
+ // handle single expiry field formatted like "MM / YY" or "MM / YYYY"
87
+ if ( ! $expiration_month & ! $expiration_year && $expiry ) {
88
+ list( $expiration_month, $expiration_year ) = array_map( 'trim', explode( '/', $expiry ) );
89
+ }
90
+
91
+ $is_valid = $this->validate_credit_card_account_number( $account_number ) && $is_valid;
92
+
93
+ $is_valid = $this->validate_credit_card_expiration_date( $expiration_month, $expiration_year ) && $is_valid;
94
+
95
+ // validate card security code
96
+ if ( $this->csc_enabled() ) {
97
+ $is_valid = $this->validate_csc( $csc ) && $is_valid;
98
+ }
99
+
100
+ /**
101
+ * Direct Payment Gateway Validate Credit Card Fields Filter.
102
+ *
103
+ * Allow actors to filter the credit card field validation.
104
+ *
105
+ * @since 3.0.0
106
+ * @param bool $is_valid true for validation to pass
107
+ * @param Payment_Gateway_Direct $this direct gateway class instance
108
+ */
109
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_validate_credit_card_fields', $is_valid, $this );
110
+ }
111
+
112
+
113
+ /**
114
+ * Validates the provided credit card expiration date
115
+ *
116
+ * @since 3.0.0
117
+ * @param string $expiration_month the credit card expiration month
118
+ * @param string $expiration_year the credit card expiration month
119
+ * @return boolean true if the card expiration date is valid, false otherwise
120
+ */
121
+ protected function validate_credit_card_expiration_date( $expiration_month, $expiration_year ) {
122
+
123
+ $is_valid = true;
124
+
125
+ if ( 2 === strlen( $expiration_year ) ) {
126
+ $expiration_year = '20' . $expiration_year;
127
+ }
128
+
129
+ // validate expiration data
130
+ $current_year = date( 'Y' );
131
+ $current_month = date( 'n' );
132
+
133
+ if ( ! ctype_digit( $expiration_month ) || ! ctype_digit( $expiration_year ) ||
134
+ $expiration_month > 12 ||
135
+ $expiration_month < 1 ||
136
+ $expiration_year < $current_year ||
137
+ ( $expiration_year == $current_year && $expiration_month < $current_month ) ||
138
+ $expiration_year > $current_year + 20
139
+ ) {
140
+ Square_Helper::wc_add_notice( esc_html__( 'Card expiration date is invalid', 'woocommerce-square' ), 'error' );
141
+ $is_valid = false;
142
+ }
143
+
144
+ return $is_valid;
145
+ }
146
+
147
+
148
+ /**
149
+ * Validates the provided credit card account number
150
+ *
151
+ * @since 3.0.0
152
+ * @param string $account_number the credit card account number
153
+ * @return boolean true if the card account number is valid, false otherwise
154
+ */
155
+ protected function validate_credit_card_account_number( $account_number ) {
156
+
157
+ $is_valid = true;
158
+
159
+ // validate card number
160
+ $account_number = str_replace( array( ' ', '-' ), '', $account_number );
161
+
162
+ if ( empty( $account_number ) ) {
163
+
164
+ Square_Helper::wc_add_notice( esc_html__( 'Card number is missing', 'woocommerce-square' ), 'error' );
165
+ $is_valid = false;
166
+
167
+ } else {
168
+
169
+ if ( strlen( $account_number ) < 12 || strlen( $account_number ) > 19 ) {
170
+ Square_Helper::wc_add_notice( esc_html__( 'Card number is invalid (wrong length)', 'woocommerce-square' ), 'error' );
171
+ $is_valid = false;
172
+ }
173
+
174
+ if ( ! ctype_digit( $account_number ) ) {
175
+ Square_Helper::wc_add_notice( esc_html__( 'Card number is invalid (only digits allowed)', 'woocommerce-square' ), 'error' );
176
+ $is_valid = false;
177
+ }
178
+
179
+ if ( ! Payment_Gateway_Helper::luhn_check( $account_number ) ) {
180
+ Square_Helper::wc_add_notice( esc_html__( 'Card number is invalid', 'woocommerce-square' ), 'error' );
181
+ $is_valid = false;
182
+ }
183
+
184
+ }
185
+
186
+ return $is_valid;
187
+ }
188
+
189
+
190
+ /**
191
+ * Validates the provided Card Security Code, adding user error messages as
192
+ * needed
193
+ *
194
+ * @since 3.0.0
195
+ * @param string $csc the customer-provided card security code
196
+ * @return boolean true if the card security code is valid, false otherwise
197
+ */
198
+ protected function validate_csc( $csc ) {
199
+
200
+ $is_valid = true;
201
+
202
+ // validate security code
203
+ if ( ! empty( $csc ) ) {
204
+
205
+ // digit validation
206
+ if ( ! ctype_digit( $csc ) ) {
207
+ Square_Helper::wc_add_notice( esc_html__( 'Card security code is invalid (only digits are allowed)', 'woocommerce-square' ), 'error' );
208
+ $is_valid = false;
209
+ }
210
+
211
+ // length validation
212
+ if ( strlen( $csc ) < 3 || strlen( $csc ) > 4 ) {
213
+ Square_Helper::wc_add_notice( esc_html__( 'Card security code is invalid (must be 3 or 4 digits)', 'woocommerce-square' ), 'error' );
214
+ $is_valid = false;
215
+ }
216
+
217
+ } elseif ( $this->csc_required() ) {
218
+
219
+ Square_Helper::wc_add_notice( esc_html__( 'Card security code is missing', 'woocommerce-square' ), 'error' );
220
+ $is_valid = false;
221
+ }
222
+
223
+ return $is_valid;
224
+ }
225
+
226
+ /**
227
+ * Handles payment processing.
228
+ *
229
+ * @see WC_Payment_Gateway::process_payment()
230
+ *
231
+ * @since 3.0.0
232
+ *
233
+ * @param int|string $order_id
234
+ * @return array associative array with members 'result' and 'redirect'
235
+ */
236
+ public function process_payment( $order_id ) {
237
+
238
+ $default = parent::process_payment( $order_id );
239
+
240
+ /**
241
+ * Direct Gateway Process Payment Filter.
242
+ *
243
+ * Allow actors to intercept and implement the process_payment() call for
244
+ * this transaction. Return an array value from this filter will return it
245
+ * directly to the checkout processing code and skip this method entirely.
246
+ *
247
+ * @since 3.0.0
248
+ * @param bool $result default true
249
+ * @param int|string $order_id order ID for the payment
250
+ * @param Payment_Gateway_Direct $this instance
251
+ */
252
+ if ( is_array( $result = apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_process_payment', true, $order_id, $this ) ) ) {
253
+ return $result;
254
+ }
255
+
256
+ // add payment information to order
257
+ $order = $this->get_order( $order_id );
258
+
259
+ try {
260
+
261
+ // handle creating or updating a payment method for registered customers if tokenization is enabled
262
+ if ( $this->supports_tokenization() && 0 !== (int) $order->get_user_id() ) {
263
+
264
+ // if already paying with an existing method, try and updated it locally and remotely
265
+ if ( ! empty( $order->payment->token ) ) {
266
+
267
+ $this->update_transaction_payment_method( $order );
268
+
269
+ // otherwise, create a new token if desired
270
+ } elseif ( $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === $order->payment_total || $this->tokenize_before_sale() ) ) {
271
+
272
+ $order = $this->get_payment_tokens_handler()->create_token( $order );
273
+ }
274
+ }
275
+
276
+ // payment failures are handled internally by do_transaction()
277
+ // the order amount will be $0 if a WooCommerce Subscriptions free trial product is being processed
278
+ // note that customer id & payment token are saved to order when create_token() is called
279
+ if ( ( '0.00' === $order->payment_total && ! $this->transaction_forced() ) || $this->do_transaction( $order ) ) {
280
+
281
+ // add transaction data for zero-dollar "orders"
282
+ if ( '0.00' === $order->payment_total ) {
283
+ $this->add_transaction_data( $order );
284
+ }
285
+
286
+ /**
287
+ * Filters the order status that's considered to be "held".
288
+ *
289
+ * @since 3.0.0
290
+ *
291
+ * @param string $status held order status
292
+ * @param \WC_Order $order order object
293
+ * @param Payment_Gateway_API_Response_Interface|null $response API response object, if any
294
+ */
295
+ $held_order_status = apply_filters( 'wc_' . $this->get_id() . '_held_order_status', 'on-hold', $order, null );
296
+
297
+ if ( $order->has_status( $held_order_status ) ) {
298
+
299
+ /**
300
+ * Although `wc_reduce_stock_levels` accepts $order, it's necessary to pass
301
+ * the order ID instead as `wc_reduce_stock_levels` reloads the order from the DB.
302
+ *
303
+ * Refer to the following PR link for more details:
304
+ * @see https://github.com/woocommerce/woocommerce-square/pull/728
305
+ */
306
+ wc_reduce_stock_levels( $order->get_id() ); // reduce stock for held orders, but don't complete payment
307
+ } else {
308
+ $order->payment_complete(); // mark order as having received payment
309
+ }
310
+
311
+ // process_payment() can sometimes be called in an admin-context
312
+ if ( isset( WC()->cart ) ) {
313
+ WC()->cart->empty_cart();
314
+ }
315
+
316
+ /**
317
+ * Payment Gateway Payment Processed Action.
318
+ *
319
+ * Fired when a payment is processed for an order.
320
+ *
321
+ * @since 3.0.0
322
+ * @param \WC_Order $order order object
323
+ * @param Payment_Gateway_Direct $this instance
324
+ */
325
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_payment_processed', $order, $this );
326
+
327
+ return array(
328
+ 'result' => 'success',
329
+ 'redirect' => $this->get_return_url( $order ),
330
+ );
331
+ }
332
+
333
+ } catch ( \Exception $e ) {
334
+
335
+ $this->mark_order_as_failed( $order, $e->getMessage() );
336
+
337
+ return array(
338
+ 'result' => 'failure',
339
+ 'message' => $e->getMessage(),
340
+ );
341
+ }
342
+
343
+ return $default;
344
+ }
345
+
346
+
347
+ /**
348
+ * Handles updating a user's payment method during payment.
349
+ *
350
+ * This allows us to check the billing address against the last used so we can determine if it needs an update.
351
+ *
352
+ * @since 3.0.0
353
+ *
354
+ * @param \WC_Order $order
355
+ * @return \WC_Order
356
+ */
357
+ protected function update_transaction_payment_method( \WC_Order $order ) {
358
+
359
+ $token = $this->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token );
360
+ $address = new Customer_Address();
361
+ $address->set_from_order( $order );
362
+
363
+ $new_billing_hash = $address->get_hash();
364
+
365
+ // if the address & token hash don't match, update
366
+ if ( $token->get_billing_hash() !== $new_billing_hash ) {
367
+
368
+ // if the API supports it, update remotely
369
+ if ( $this->get_api()->supports_update_tokenized_payment_method() ) {
370
+
371
+ $response = null;
372
+
373
+ try {
374
+
375
+ $response = $this->get_api()->update_tokenized_payment_method( $order );
376
+
377
+ // if an address was passed and the token was updated remotely, update the billing hash
378
+ if ( $response->transaction_approved() ) {
379
+
380
+ $token->set_billing_hash( $new_billing_hash );
381
+
382
+ } else {
383
+
384
+ if ( $response->get_status_message() ) {
385
+ $message = $response->get_status_code() ? $response->get_status_code() . ' - ' . $response->get_status_message() : $response->get_status_message();
386
+ } else {
387
+ $message = __( 'Unknown error', 'woocommerce-square' );
388
+ }
389
+
390
+ throw new \Exception( $message );
391
+ }
392
+
393
+ } catch ( \Exception $exception ) {
394
+
395
+ $message = sprintf(
396
+ esc_html__( 'Payment method address could not be updated. %s', 'woocommerce-square' ),
397
+ $exception->getMessage()
398
+ );
399
+
400
+ $order->add_order_note( $message );
401
+
402
+ if ( $this->debug_log() ) {
403
+ $this->get_plugin()->log( $message, $this->get_id() );
404
+ }
405
+ }
406
+
407
+ } else {
408
+
409
+ // updating remotely isn't supported, so just update the hash locally
410
+ $token->set_billing_hash( $new_billing_hash );
411
+ }
412
+ }
413
+
414
+ // don't halt payment if this fails
415
+ $this->get_payment_tokens_handler()->update_token( $order->get_user_id(), $token );
416
+
417
+ return $order;
418
+ }
419
+
420
+
421
+ /**
422
+ * Add payment and transaction information as class members of WC_Order
423
+ * instance. The standard information that can be added includes:
424
+ *
425
+ * $order->payment_total - the payment total
426
+ * $order->customer_id - optional payment gateway customer id (useful for tokenized payments for certain gateways, etc)
427
+ * $order->payment->account_number - the credit card or checking account number
428
+ * $order->payment->last_four - the last four digits of the account number
429
+ * $order->payment->card_type - the card type (e.g. visa) derived from the account number
430
+ * $order->payment->routing_number - account routing number (check transactions only)
431
+ * $order->payment->account_type - optional type of account one of 'checking' or 'savings' if type is 'check'
432
+ * $order->payment->card_type - optional card type, ie one of 'visa', etc
433
+ * $order->payment->exp_month - the 2 digit credit card expiration month (for credit card gateways), e.g. 07
434
+ * $order->payment->exp_year - the 2 digit credit card expiration year (for credit card gateways), e.g. 17
435
+ * $order->payment->csc - the card security code (for credit card gateways)
436
+ * $order->payment->check_number - optional check number (check transactions only)
437
+ * $order->payment->drivers_license_number - optional driver license number (check transactions only)
438
+ * $order->payment->drivers_license_state - optional driver license state code (check transactions only)
439
+ * $order->payment->token - payment token (for tokenized transactions)
440
+ *
441
+ * Note that not all gateways will necessarily pass or require all of the
442
+ * above. These represent the most common attributes used among a variety
443
+ * of gateways, it's up to the specific gateway implementation to make use
444
+ * of, or ignore them, or add custom ones by overridding this method.
445
+ *
446
+ * @since 3.0.0
447
+ * @see WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway::get_order()
448
+ * @param int|\WC_Order $order_id order ID being processed
449
+ * @return \WC_Order object with payment and transaction information attached
450
+ */
451
+ public function get_order( $order_id ) {
452
+
453
+ $order = parent::get_order( $order_id );
454
+
455
+ // payment info
456
+ if ( Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-account-number' ) && ! Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) {
457
+
458
+ // common attributes
459
+ $order->payment->account_number = str_replace( array( ' ', '-' ), '', Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-account-number' ) );
460
+ $order->payment->last_four = substr( $order->payment->account_number, -4 );
461
+
462
+ if ( $this->is_credit_card_gateway() ) {
463
+
464
+ // credit card specific attributes
465
+ $order->payment->card_type = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-card-type' );
466
+ $order->payment->exp_month = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-exp-month' );
467
+ $order->payment->exp_year = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-exp-year' );
468
+
469
+ // add card type for gateways that don't require it displayed at checkout
470
+ if ( empty( $order->payment->card_type ) ) {
471
+ $order->payment->card_type = Payment_Gateway_Helper::card_type_from_account_number( $order->payment->account_number );
472
+ }
473
+
474
+ // handle single expiry field formatted like "MM / YY" or "MM / YYYY"
475
+ if ( Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-expiry' ) ) {
476
+ list( $order->payment->exp_month, $order->payment->exp_year ) = array_map( 'trim', explode( '/', Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-expiry' ) ) );
477
+ }
478
+
479
+ // add CSC if enabled
480
+ if ( $this->csc_enabled() ) {
481
+ $order->payment->csc = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-csc' );
482
+ }
483
+ }
484
+
485
+ } elseif ( Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) {
486
+
487
+ // paying with tokenized payment method (we've already verified that this token exists in the validate_fields method)
488
+ $token = $this->get_payment_tokens_handler()->get_token( $order->get_user_id(), Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) );
489
+
490
+ $order->payment->token = $token->get_id();
491
+ $order->payment->account_number = $token->get_last_four();
492
+ $order->payment->last_four = $token->get_last_four();
493
+
494
+ if ( $this->is_credit_card_gateway() ) {
495
+
496
+ // credit card specific attributes
497
+ $order->payment->card_type = $token->get_card_type();
498
+ $order->payment->exp_month = $token->get_exp_month();
499
+ $order->payment->exp_year = $token->get_exp_year();
500
+
501
+ if ( $this->csc_enabled_for_tokens() ) {
502
+ $order->payment->csc = Square_Helper::get_post( 'wc-' . $this->get_id_dasherized() . '-csc' );
503
+ }
504
+ }
505
+ // make this the new default payment token
506
+ $this->get_payment_tokens_handler()->set_default_token( $order->get_user_id(), $token );
507
+ }
508
+
509
+ // standardize expiration date year to 2 digits
510
+ if ( ! empty( $order->payment->exp_year ) && 4 === strlen( $order->payment->exp_year ) ) {
511
+ $order->payment->exp_year = substr( $order->payment->exp_year, 2 );
512
+ }
513
+
514
+ /**
515
+ * Direct Gateway Get Order Filter.
516
+ *
517
+ * Allow actors to modify the order object.
518
+ *
519
+ * @since 3.0.0
520
+ * @param \WC_Order $order order object
521
+ * @param Payment_Gateway_Direct $this instance
522
+ */
523
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_get_order', $order, $this );
524
+ }
525
+
526
+ /**
527
+ * Performs a credit card transaction for the given order and returns the result.
528
+ *
529
+ * @since 3.0.0
530
+ *
531
+ * @param \WC_Order $order the order object
532
+ * @param Payment_Gateway_API_Response_Interface $response optional credit card transaction response
533
+ * @return Payment_Gateway_API_Response_Interface the response
534
+ * @throws \Exception network timeouts, etc
535
+ */
536
+ protected function do_credit_card_transaction( $order, $response = null ) {
537
+
538
+ if ( is_null( $response ) ) {
539
+ if ( $this->perform_credit_card_charge( $order ) ) {
540
+ $response = $this->get_api()->credit_card_charge( $order );
541
+ } else {
542
+ $response = $this->get_api()->credit_card_authorization( $order );
543
+ }
544
+ }
545
+
546
+ // success! update order record
547
+ if ( $response->transaction_approved() ) {
548
+
549
+ $last_four = substr( $order->payment->account_number, -4 );
550
+
551
+ // use direct card type if set, or try to guess it from card number
552
+ if ( ! empty( $order->payment->card_type ) ) {
553
+ $card_type = $order->payment->card_type;
554
+ } elseif ( $first_four = substr( $order->payment->account_number, 0, 4 ) ) {
555
+ $card_type = Payment_Gateway_Helper::card_type_from_account_number( $first_four );
556
+ } else {
557
+ $card_type = 'card';
558
+ }
559
+
560
+ // credit card order note
561
+ $message = sprintf(
562
+ /* translators: Placeholders: %1$s - payment method title, %2$s - environment ("Test"), %3$s - transaction type (authorization/charge), %4$s - card type (mastercard, visa, ...), %5$s - last four digits of the card */
563
+ esc_html__( '%1$s %2$s %3$s Approved: %4$s ending in %5$s', 'woocommerce-square' ),
564
+ $this->get_method_title(),
565
+ $this->is_test_environment() ? esc_html_x( 'Test', 'noun, software environment', 'woocommerce-square' ) : '',
566
+ $this->perform_credit_card_authorization( $order ) ? esc_html_x( 'Authorization', 'credit card transaction type', 'woocommerce-square' ) : esc_html_x( 'Charge', 'noun, credit card transaction type', 'woocommerce-square' ),
567
+ Payment_Gateway_Helper::payment_type_to_name( $card_type ),
568
+ $last_four
569
+ );
570
+
571
+ // add the expiry date if it is available
572
+ if ( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ) {
573
+
574
+ $message .= ' ' . sprintf(
575
+ /** translators: Placeholders: %s - credit card expiry date */
576
+ __( '(expires %s)', 'woocommerce-square' ),
577
+ esc_html( $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) )
578
+ );
579
+ }
580
+
581
+ // adds the transaction id (if any) to the order note
582
+ if ( $response->get_transaction_id() ) {
583
+ /* translators: Placeholders: %s - transaction ID */
584
+ $message .= ' ' . sprintf( esc_html__( '(Transaction ID %s)', 'woocommerce-square' ), $response->get_transaction_id() );
585
+ }
586
+
587
+ /**
588
+ * Direct Gateway Credit Card Transaction Approved Order Note Filter.
589
+ *
590
+ * Allow actors to modify the order note added when a Credit Card transaction
591
+ * is approved.
592
+ *
593
+ * @since 3.0.0
594
+ *
595
+ * @param string $message order note
596
+ * @param \WC_Order $order order object
597
+ * @param Payment_Gateway_API_Response_Interface $response transaction response
598
+ * @param Payment_Gateway_Direct $this instance
599
+ */
600
+ $message = apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_credit_card_transaction_approved_order_note', $message, $order, $response, $this );
601
+
602
+ $order->add_order_note( $message );
603
+
604
+ }
605
+
606
+ return $response;
607
+
608
+ }
609
+
610
+
611
+ /**
612
+ * Create a transaction.
613
+ *
614
+ * @since 3.0.0
615
+ *
616
+ * @param \WC_Order $order the order object
617
+ * @return bool
618
+ * @throws \Exception
619
+ */
620
+ protected function do_transaction( $order ) {
621
+
622
+ // perform the credit card or check transaction
623
+ if ( $this->is_credit_card_gateway() ) {
624
+ $response = $this->do_credit_card_transaction( $order );
625
+ } else {
626
+ $do_payment_type_transaction = 'do_' . $this->get_payment_type() . '_transaction';
627
+ $response = $this->$do_payment_type_transaction( $order );
628
+ }
629
+
630
+ // handle the response
631
+ if ( $response->transaction_approved() || $response->transaction_held() ) {
632
+
633
+ if ( $this->supports_tokenization() && 0 != $order->get_user_id() && $this->get_payment_tokens_handler()->should_tokenize() &&
634
+ ( $order->payment_total > 0 && ( $this->tokenize_with_sale() || $this->tokenize_after_sale() ) ) ) {
635
+
636
+ try {
637
+ $order = $this->get_payment_tokens_handler()->create_token( $order, $response );
638
+ } catch ( \Exception $e ) {
639
+
640
+ // handle the case of a "tokenize-after-sale" request failing by marking the order as on-hold with an explanatory note
641
+ if ( ! $response->transaction_held() && ! ( $this->supports( self::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->perform_credit_card_authorization( $order ) ) ) {
642
+
643
+ // transaction has already been successful, but we've encountered an issue with the post-tokenization, add an order note to that effect and continue on
644
+ $message = sprintf(
645
+ /* translators: Placeholders: %s - failure message */
646
+ esc_html__( 'Tokenization Request Failed: %s', 'woocommerce-square' ),
647
+ $e->getMessage()
648
+ );
649
+
650
+ $this->mark_order_as_held( $order, $message, $response );
651
+
652
+ } else {
653
+
654
+ // transaction has already been successful, but we've encountered an issue with the post-tokenization, add an order note to that effect and continue on
655
+ $message = sprintf(
656
+ /* translators: Placeholders: %1$s - payment method title, %2$s - failure message */
657
+ esc_html__( '%1$s Tokenization Request Failed: %2$s', 'woocommerce-square' ),
658
+ $this->get_method_title(),
659
+ $e->getMessage()
660
+ );
661
+
662
+ $order->add_order_note( $message );
663
+ }
664
+ }
665
+ }
666
+
667
+ // add the standard transaction data
668
+ $this->add_transaction_data( $order, $response );
669
+
670
+ // allow the concrete class to add any gateway-specific transaction data to the order
671
+ $this->add_payment_gateway_transaction_data( $order, $response );
672
+
673
+ // if the transaction was held (ie fraud validation failure) mark it as such
674
+ // TODO: consider checking whether the response *was* an authorization, rather than blanket-assuming it was because of the settings. There are times when an auth will be used rather than charge, ie when performing in-plugin AVS handling (moneris)
675
+ if ( $response->transaction_held() || ( $this->supports( self::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->perform_credit_card_authorization( $order ) ) ) {
676
+ // TODO: need to make this more flexible, and not force the message to 'Authorization only transaction' for auth transactions (re moneris efraud handling)
677
+ /* translators: This is a message describing that the transaction in question only performed a credit card authorization and did not capture any funds. */
678
+ $this->mark_order_as_held( $order, $this->supports( self::FEATURE_CREDIT_CARD_AUTHORIZATION ) && $this->perform_credit_card_authorization( $order ) ? esc_html__( 'Authorization only transaction', 'woocommerce-square' ) : $response->get_status_message(), $response );
679
+ }
680
+
681
+ return true;
682
+
683
+ } else { // failure
684
+
685
+ return $this->do_transaction_failed_result( $order, $response );
686
+
687
+ }
688
+ }
689
+
690
+
691
+ /** Add Payment Method feature ********************************************/
692
+
693
+
694
+ /**
695
+ * Entry method for the Add Payment Method feature flow. Note this is *not*
696
+ * stubbed in the WC_Payment_Gateway abstract class, but is called if the
697
+ * gateway declares support for it.
698
+ *
699
+ * @since 3.0.0
700
+ */
701
+ public function add_payment_method() {
702
+
703
+ assert( $this->supports_add_payment_method() );
704
+
705
+ $order = $this->get_order_for_add_payment_method();
706
+
707
+ try {
708
+
709
+ $result = $this->do_add_payment_method_transaction( $order );
710
+
711
+ } catch ( \Exception $e ) {
712
+
713
+ $result = array(
714
+ /* translators: Placeholders: %s - failure message. Payment method as in a specific credit card, e-check or bank account */
715
+ 'message' => sprintf( esc_html__( 'Oops, adding your new payment method failed: %s', 'woocommerce-square' ), $e->getMessage() ),
716
+ 'success' => false,
717
+ );
718
+ }
719
+
720
+ Square_Helper::wc_add_notice( $result['message'], $result['success'] ? 'success' : 'error' );
721
+
722
+ if ( $result['success'] ) {
723
+ $redirect_url = wc_get_account_endpoint_url( 'payment-methods' );
724
+ } else {
725
+ $redirect_url = wc_get_endpoint_url( 'add-payment-method' );
726
+ }
727
+
728
+ wp_safe_redirect( $redirect_url );
729
+ exit();
730
+ }
731
+
732
+
733
+ /**
734
+ * Perform the transaction to add the customer's payment method to their
735
+ * account
736
+ *
737
+ * @since 3.0.0
738
+ * @return array result with success/error message and request status (success/failure)
739
+ * @throws \Exception
740
+ */
741
+ protected function do_add_payment_method_transaction( \WC_Order $order ) {
742
+
743
+ $response = $this->get_api()->tokenize_payment_method( $order );
744
+
745
+ if ( $response->transaction_approved() ) {
746
+
747
+ $token = $response->get_payment_token();
748
+
749
+ // set the token to the user account
750
+ $this->get_payment_tokens_handler()->add_token( $order->get_user_id(), $token );
751
+
752
+ // order note based on gateway type
753
+ if ( $this->is_credit_card_gateway() ) {
754
+
755
+ /* translators: Payment method as in a specific credit card. Placeholders: %1$s - card type (visa, mastercard, ...), %2$s - last four digits of the card, %3$s - card expiry date */
756
+ $message = sprintf( esc_html__( 'Nice! New payment method added: %1$s ending in %2$s (expires %3$s)', 'woocommerce-square' ),
757
+ $token->get_type_full(),
758
+ $token->get_last_four(),
759
+ $token->get_exp_date()
760
+ );
761
+
762
+ } else {
763
+ /* translators: Payment method as in a specific credit card, e-check or bank account */
764
+ $message = esc_html__( 'Nice! New payment method added.', 'woocommerce-square' );
765
+ }
766
+
767
+ // add transaction data to user meta
768
+ $this->add_add_payment_method_transaction_data( $response );
769
+
770
+ // add customer data, primarily customer ID to user meta
771
+ $this->add_add_payment_method_customer_data( $order, $response );
772
+
773
+ /**
774
+ * Fires after a new payment method is added by a customer.
775
+ *
776
+ * @since 3.0.0
777
+ *
778
+ * @param string $token_id new token ID
779
+ * @param int $user_id user ID
780
+ * @param Payment_Gateway_API_Response_Interface $response API response object
781
+ */
782
+ do_action( 'wc_payment_gateway_' . $this->get_id() . '_payment_method_added', $token->get_id(), $order->get_user_id(), $response );
783
+
784
+ $result = array( 'message' => $message, 'success' => true );
785
+
786
+ } else {
787
+
788
+ if ( $response->get_status_code() && $response->get_status_message() ) {
789
+ $message = sprintf( esc_html__( 'Status code %s: %s', 'woocommerce-square' ), $response->get_status_code(), $response->get_status_message() );
790
+ } elseif ( $response->get_status_code() ) {
791
+ $message = sprintf( esc_html__( 'Status code: %s', 'woocommerce-square' ), $response->get_status_code() );
792
+ } elseif ( $response->get_status_message() ) {
793
+ $message = sprintf( esc_html__( 'Status message: %s', 'woocommerce-square' ), $response->get_status_message() );
794
+ } else {
795
+ $message = 'Unknown Error';
796
+ }
797
+
798
+ $result = array( 'message' => $message, 'success' => false );
799
+ }
800
+
801
+ /**
802
+ * Add Payment Method Transaction Result Filter.
803
+ *
804
+ * Filter the result data from an add payment method transaction attempt -- this
805
+ * can be used to control the notice message displayed and whether the
806
+ * user is redirected back to the My Account page or remains on the add
807
+ * new payment method screen
808
+ *
809
+ * @since 3.0.0
810
+ * @param array $result {
811
+ * @type string $message notice message to render
812
+ * @type bool $success true to redirect to my account, false to stay on page
813
+ * }
814
+ * @param WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Create_Payment_Token_Response $response instance
815
+ * @param \WC_Order $order order instance
816
+ * @param Payment_Gateway_Direct $this direct gateway instance
817
+ */
818
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_add_payment_method_transaction_result', $result, $response, $order, $this );
819
+ }
820
+
821
+
822
+ /**
823
+ * Creates the order required for adding a new payment method. Note that
824
+ * a mock order is generated as there is no actual order associated with the
825
+ * request.
826
+ *
827
+ * @since 3.0.0
828
+ * @return \WC_Order generated order object
829
+ */
830
+ protected function get_order_for_add_payment_method() {
831
+
832
+ // mock order, as all gateway API implementations require an order object for tokenization
833
+ $order = new \WC_Order( 0 );
834
+ $order = $this->get_order( $order );
835
+
836
+ $user = get_userdata( get_current_user_id() );
837
+
838
+ $properties = array(
839
+ 'currency' => get_woocommerce_currency(), // default to base store currency
840
+ 'customer_id' => $user->ID,
841
+ );
842
+
843
+ $defaults = array(
844
+ // billing
845
+ 'billing_first_name' => '',
846
+ 'billing_last_name' => '',
847
+ 'billing_company' => '',
848
+ 'billing_address_1' => '',
849
+ 'billing_address_2' => '',
850
+ 'billing_city' => '',
851
+ 'billing_postcode' => '',
852
+ 'billing_state' => '',
853
+ 'billing_country' => '',
854
+ 'billing_phone' => '',
855
+ 'billing_email' => $user->user_email,
856
+
857
+ // shipping
858
+ 'shipping_first_name' => '',
859
+ 'shipping_last_name' => '',
860
+ 'shipping_company' => '',
861
+ 'shipping_address_1' => '',
862
+ 'shipping_address_2' => '',
863
+ 'shipping_city' => '',
864
+ 'shipping_postcode' => '',
865
+ 'shipping_state' => '',
866
+ 'shipping_country' => '',
867
+ );
868
+
869
+ foreach ( $defaults as $prop => $value ) {
870
+
871
+ $value = ! empty( $user->$prop ) ? $user->$prop : $value;
872
+
873
+ if ( ! empty( $value ) ) {
874
+ $properties[ $prop ] = $value;
875
+ }
876
+ }
877
+
878
+ $order = Order_Compatibility::set_props( $order, $properties );
879
+
880
+ // other default info
881
+ $order->customer_id = $this->get_customer_id( $order->get_user_id() );
882
+
883
+ /* translators: Placeholders: %1$s - site title, %2$s - customer email. Payment method as in a specific credit card, e-check or bank account */
884
+ $order->description = sprintf( esc_html__( '%1$s - Add Payment Method for %2$s', 'woocommerce-square' ), sanitize_text_field( Square_Helper::get_site_name() ), $properties['billing_email'] );
885
+
886
+ // force zero amount
887
+ $order->payment_total = '0.00';
888
+
889
+ /**
890
+ * Direct Gateway Get Order for Add Payment Method Filter.
891
+ *
892
+ * Allow actors to modify the order object used for an add payment method
893
+ * transaction.
894
+ *
895
+ * @since 3.0.0
896
+ * @param \WC_Order $order order object
897
+ * @param Payment_Gateway_Direct $this instance
898
+ */
899
+ return apply_filters( 'wc_payment_gateway_' . $this->get_id() . '_get_order_for_add_payment_method', $order, $this );
900
+ }
901
+
902
+
903
+ /**
904
+ * Add customer data as part of the add payment method transaction, primarily
905
+ * customer ID
906
+ *
907
+ * @since 3.0.0
908
+ * @param \WC_Order $order mock order
909
+ * @param \WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Create_Payment_Token_Response $response
910
+ */
911
+ protected function add_add_payment_method_customer_data( $order, $response ) {
912
+ $user_id = $order->get_user_id();
913
+
914
+ // set customer ID from response if available
915
+ if ( $this->supports_customer_id() && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) {
916
+
917
+ $order->customer_id = $customer_id = $response->get_customer_id();
918
+
919
+ } else {
920
+
921
+ // default to the customer ID on "order"
922
+ $customer_id = $order->customer_id;
923
+ }
924
+
925
+ // update the user
926
+ if ( 0 != $user_id ) {
927
+ $this->update_customer_id( $user_id, $customer_id );
928
+ }
929
+ }
930
+
931
+
932
+ /**
933
+ * Adds data from the add payment method transaction, primarily:
934
+ *
935
+ * + transaction ID
936
+ * + transaction date
937
+ * + transaction environment
938
+ *
939
+ * @since 3.0.0
940
+ *
941
+ * @param WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Create_Payment_Token_Response $response
942
+ */
943
+ protected function add_add_payment_method_transaction_data( $response ) {
944
+
945
+ $user_meta_key = '_wc_' . $this->get_id() . '_add_payment_method_transaction_data';
946
+
947
+ $data = (array) get_user_meta( get_current_user_id(), $user_meta_key, true );
948
+
949
+ $new_data = array(
950
+ 'trans_id' => $response->get_transaction_id() ? $response->get_transaction_id() : null,
951
+ 'trans_date' => current_time( 'mysql' ),
952
+ 'environment' => $this->get_environment(),
953
+ );
954
+
955
+ $data[] = array_merge( $new_data, $this->get_add_payment_method_payment_gateway_transaction_data( $response ) );
956
+
957
+ // only keep the 5 most recent transactions
958
+ if ( count( $data ) > 5 ) {
959
+ array_shift( $data );
960
+ }
961
+
962
+ update_user_meta( get_current_user_id(), $user_meta_key, array_filter( $data ) );
963
+ }
964
+
965
+
966
+ /**
967
+ * Allow gateway implementations to add additional data to the data saved
968
+ * during the add payment method transaction
969
+ *
970
+ * @since 3.0.0
971
+ * @param WooCommerce\Square\Framework\PaymentGateway\Api\Payment_Gateway_API_Create_Payment_Token_Response $response create payment token response
972
+ * @return array
973
+ */
974
+ protected function get_add_payment_method_payment_gateway_transaction_data( $response ) {
975
+
976
+ // stub method
977
+ return array();
978
+ }
979
+
980
+
981
+ /** Getters ******************************************************/
982
+
983
+
984
+ /**
985
+ * Returns true if this is a direct type gateway
986
+ *
987
+ * @since 3.0.0
988
+ * @return boolean if this is a direct payment gateway
989
+ */
990
+ public function is_direct_gateway() {
991
+ return true;
992
+ }
993
+
994
+
995
+ /**
996
+ * Returns true if a transaction should be forced (meaning payment
997
+ * processed even if the order amount is 0). This is useful mostly for
998
+ * testing situations
999
+ *
1000
+ * @since 3.0.0
1001
+ * @return boolean true if the transaction request should be forced
1002
+ */
1003
+ public function transaction_forced() {
1004
+ return false;
1005
+ }
1006
+
1007
+ }
includes/Framework/PaymentGateway/Payment_Gateway_Helper.php ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway;
4
+
5
+ defined( 'ABSPATH' ) or exit;
6
+
7
+ /**
8
+ * Payment Gateway Helper Class
9
+ *
10
+ * @since 3.0.0
11
+ */
12
+ class Payment_Gateway_Helper {
13
+
14
+
15
+ /** @var string the Visa card type ID **/
16
+ const CARD_TYPE_VISA = 'visa';
17
+
18
+ /** @var string the MasterCard card type ID **/
19
+ const CARD_TYPE_MASTERCARD = 'mastercard';
20
+
21
+ /** @var string the American Express card type ID **/
22
+ const CARD_TYPE_AMEX = 'amex';
23
+
24
+ /** @var string the Diners Club card type ID **/
25
+ const CARD_TYPE_DINERSCLUB = 'dinersclub';
26
+
27
+ /** @var string the Discover card type ID **/
28
+ const CARD_TYPE_DISCOVER = 'discover';
29
+
30
+ /** @var string the JCB card type ID **/
31
+ const CARD_TYPE_JCB = 'jcb';
32
+
33
+ /** @var string the CarteBleue card type ID **/
34
+ const CARD_TYPE_CARTEBLEUE = 'cartebleue';
35
+
36
+ /** @var string the Maestro card type ID **/
37
+ const CARD_TYPE_MAESTRO = 'maestro';
38
+
39
+ /** @var string the Laser card type ID **/
40
+ const CARD_TYPE_LASER = 'laser';
41
+
42
+
43
+ /**
44
+ * Perform standard luhn check. Algorithm:
45
+ *
46
+ * 1. Double the value of every second digit beginning with the second-last right-hand digit.
47
+ * 2. Add the individual digits comprising the products obtained in step 1 to each of the other digits in the original number.
48
+ * 3. Subtract the total obtained in step 2 from the next higher number ending in 0.
49
+ * 4. This number should be the same as the last digit (the check digit). If the total obtained in step 2 is a number ending in zero (30, 40 etc.), the check digit is 0.
50
+ *
51
+ * @since 3.0.0
52
+ * @param string $account_number the credit card number to check
53
+ * @return bool true if $account_number passes the check, false otherwise
54
+ */
55
+ public static function luhn_check( $account_number ) {
56
+
57
+ for ( $sum = 0, $i = 0, $ix = strlen( $account_number ); $i < $ix - 1; $i++) {
58
+
59
+ $weight = substr( $account_number, $ix - ( $i + 2 ), 1 ) * ( 2 - ( $i % 2 ) );
60
+ $sum += $weight < 10 ? $weight : $weight - 9;
61
+
62
+ }
63
+
64
+ return substr( $account_number, $ix - 1 ) == ( ( 10 - $sum % 10 ) % 10 );
65
+ }
66
+
67
+
68
+ /**
69
+ * Normalize a card type to a standard type ID and account for variations.
70
+ *
71
+ * @since 3.0.0
72
+ * @param string $card_type the card type to normalize
73
+ * @return string
74
+ */
75
+ public static function normalize_card_type( $card_type ) {
76
+
77
+ $card_types = self::get_card_types();
78
+
79
+ $card_type = strtolower( $card_type );
80
+
81
+ // stop here if the provided card type is already normalized
82
+ if ( in_array( $card_type, array_keys( $card_types ), true ) ) {
83
+ return $card_type;
84
+ }
85
+
86
+ $variations = wp_list_pluck( $card_types, 'variations' );
87
+
88
+ // if the provided card type matches a known variation, return the normalized card type
89
+ foreach ( $variations as $valid_type => $vars ) {
90
+
91
+ if ( in_array( $card_type, $vars, true ) ) {
92
+ $card_type = $valid_type;
93
+ break;
94
+ }
95
+ }
96
+
97
+ // otherwise, let it through unaltered
98
+ return $card_type;
99
+ }
100
+
101
+
102
+ /**
103
+ * Determine the credit card type from a given account number (only first 4
104
+ * required)
105
+ *
106
+ * @since 3.0.0
107
+ * @param string $account_number the credit card account number
108
+ * @return string the credit card type
109
+ */
110
+ public static function card_type_from_account_number( $account_number ) {
111
+
112
+ // card type regex patterns from https://github.com/stripe/jquery.payment/blob/master/src/jquery.payment.coffee
113
+ $types = array(
114
+ self::CARD_TYPE_VISA => '/^4/',
115
+ self::CARD_TYPE_MASTERCARD => '/^(5[1-5]|2[2-7])/',
116
+ self::CARD_TYPE_AMEX => '/^3[47]/',
117
+ self::CARD_TYPE_DINERSCLUB => '/^(36|38|30[0-5])/',
118
+ self::CARD_TYPE_DISCOVER => '/^(6011|65|64[4-9]|622)/',
119
+ self::CARD_TYPE_JCB => '/^35/',
120
+ self::CARD_TYPE_MAESTRO => '/^(5018|5020|5038|6304|6759|676[1-3])/',
121
+ self::CARD_TYPE_LASER => '/^(6706|6771|6709)/',
122
+ );
123
+
124
+ foreach ( $types as $type => $pattern ) {
125
+
126
+ if ( 1 === preg_match( $pattern, $account_number ) ) {
127
+ return $type;
128
+ }
129
+ }
130
+
131
+ return null;
132
+ }
133
+
134
+
135
+ /**
136
+ * Translates a credit card type or bank account name to a full name,
137
+ * e.g. 'mastercard' => 'MasterCard' or 'savings' => 'eCheck'
138
+ *
139
+ * @since 3.0.0
140
+ * @param string $payment_type the credit card or bank type, ie 'mastercard', 'amex', 'checking'
141
+ * @return string the credit card or bank account name, ie 'MasterCard', 'American Express', 'Checking Account'
142
+ */
143
+ public static function payment_type_to_name( $payment_type ) {
144
+
145
+ $name = '';
146
+
147
+ // normalize for backwards compatibility with gateways that pass the card type directly from Payment_Gateway::get_card_types()
148
+ $type = self::normalize_card_type( $payment_type );
149
+
150
+ // known payment type names, excluding credit cards
151
+ $payment_types = array(
152
+ 'paypal' => esc_html__( 'PayPal', 'woocommerce-square' ),
153
+ 'checking' => esc_html__( 'Checking Account', 'woocommerce-square' ),
154
+ 'savings' => esc_html__( 'Savings Account', 'woocommerce-square' ),
155
+ 'card' => esc_html__( 'Credit / Debit Card', 'woocommerce-square' ),
156
+ 'bank' => esc_html__( 'Bank Account', 'woocommerce-square' ),
157
+ );
158
+
159
+ // add the credit card names
160
+ $payment_types = array_merge( wp_list_pluck( self::get_card_types(), 'name' ), $payment_types );
161
+
162
+ if ( isset( $payment_types[ $type ] ) ) {
163
+ $name = $payment_types[ $type ];
164
+ } elseif ( '' === $type ) {
165
+ $name = esc_html_x( 'Account', 'payment method type', 'woocommerce-square' );
166
+ } else {
167
+ $name = ucwords( str_replace( '-', ' ', $type ) );
168
+ }
169
+
170
+ /**
171
+ * Payment Gateway Type to Name Filter.
172
+ *
173
+ * Allow actors to modify the name returned given a payment type.
174
+ *
175
+ * @since 3.0.0
176
+ * @param string $name nice payment type name, e.g. American Express
177
+ * @param string $type payment type, e.g. amex
178
+ */
179
+ return apply_filters( 'wc_payment_gateway_payment_type_to_name', $name, $type );
180
+ }
181
+
182
+
183
+ /**
184
+ * Gets the known card types and their variations.
185
+ *
186
+ * Returns the card types in the format:
187
+ *
188
+ * 'mastercard' {
189
+ * 'name' => 'MasterCard',
190
+ * 'variations' => array( 'mc' ),
191
+ * }
192
+ *
193
+ * @since 3.0.0
194
+ *
195
+ * @return array
196
+ */
197
+ public static function get_card_types() {
198
+
199
+ return array(
200
+ self::CARD_TYPE_VISA => array(
201
+ 'name' => esc_html_x( 'Visa', 'credit card type', 'woocommerce-square' ),
202
+ 'variations' => array(),
203
+ ),
204
+ self::CARD_TYPE_MASTERCARD => array(
205
+ 'name' => esc_html_x( 'MasterCard', 'credit card type', 'woocommerce-square' ),
206
+ 'variations' => array( 'mc' ),
207
+ ),
208
+ self::CARD_TYPE_AMEX => array(
209
+ 'name' => esc_html_x( 'American Express', 'credit card type', 'woocommerce-square' ),
210
+ 'variations' => array( 'americanexpress' ),
211
+ ),
212
+ self::CARD_TYPE_DINERSCLUB => array(
213
+ 'name' => esc_html_x( 'Diners Club', 'credit card type', 'woocommerce-square' ),
214
+ 'variations' => array( 'diners' ),
215
+ ),
216
+ self::CARD_TYPE_DISCOVER => array(
217
+ 'name' => esc_html_x( 'Discover', 'credit card type', 'woocommerce-square' ),
218
+ 'variations' => array( 'disc' ),
219
+ ),
220
+ self::CARD_TYPE_JCB => array(
221
+ 'name' => esc_html_x( 'JCB', 'credit card type', 'woocommerce-square' ),
222
+ 'variations' => array(),
223
+ ),
224
+ self::CARD_TYPE_CARTEBLEUE => array(
225
+ 'name' => esc_html_x( 'CarteBleue', 'credit card type', 'woocommerce-square' ),
226
+ 'variations' => array(),
227
+ ),
228
+ self::CARD_TYPE_MAESTRO => array(
229
+ 'name' => esc_html_x( 'Maestro', 'credit card type', 'woocommerce-square' ),
230
+ 'variations' => array(),
231
+ ),
232
+ self::CARD_TYPE_LASER => array(
233
+ 'name' => esc_html_x( 'Laser', 'credit card type', 'woocommerce-square' ),
234
+ 'variations' => array(),
235
+ ),
236
+ );
237
+ }
238
+ }
includes/Framework/PaymentGateway/Payment_Gateway_My_Payment_Methods.php ADDED
@@ -0,0 +1,970 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WooCommerce\Square\Framework\PaymentGateway;
4
+ use WooCommerce\Square\Plugin;
5
+ use WooCommerce\Square\Framework\PaymentGateway\PaymentTokens\Payment_Gateway_Payment_Token;
6
+ use WooCommerce\Square\Framework\Square_Helper;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ /**
11
+ * My Payment Methods Class
12
+ *
13
+ * Renders the My Payment Methods table on the My Account page and handles
14
+ * any associated actions (deleting a payment method, etc)
15
+ *
16
+ * @since 3.0.0
17
+ */
18
+ class Payment_Gateway_My_Payment_Methods {
19
+
20
+
21
+ /** @var Payment_Gateway_Plugin */
22
+ protected $plugin;
23
+
24
+ /** @var Payment_Gateway_Payment_Token[] array of token objects */
25
+ protected $tokens;
26
+
27
+ /** @var Payment_Gateway_Payment_Token[] array of token objects */
28
+ protected $credit_card_tokens;
29
+
30
+ /** @var Payment_Gateway_Payment_Token[] array of token objects */
31
+ protected $echeck_tokens;
32
+
33
+ /** @var bool true if there are tokens */
34
+ protected $has_tokens;
35
+
36
+
37
+ /**
38
+ * Setup Class
39
+ *
40
+ * Note: this constructor executes during the `wp` action
41
+ *
42
+ * @param Payment_Gateway_Plugin $plugin gateway plugin
43
+ * @since 3.0.0
44
+ */
45
+ public function __construct( $plugin ) {
46
+
47
+ $this->plugin = $plugin;
48
+
49
+ add_action( 'wp', array( $this, 'init' ) );
50
+
51
+ // save a payment method via AJAX
52
+ add_action( 'wp_ajax_wc_' . $this->get_plugin()->get_id() . '_save_payment_method', array( $this, 'ajax_save_payment_method' ) );
53
+ }
54
+
55
+
56
+ /**
57
+ * Initializes the My Payment Methods table
58
+ *
59
+ * @since 3.0.0
60
+ */
61
+ public function init() {
62
+
63
+ if ( ! $this->is_payment_methods_page() ) {
64
+ return;
65
+ }
66
+
67
+ // load all tokens for the given plugin
68
+ $this->load_tokens();
69
+
70
+ // styles/scripts
71
+ add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_styles_scripts' ) );
72
+
73
+ // render the My Payment Methods section
74
+ // TODO: merge our payment methods data into the core table and remove this in a future version {CW 2016-05-17}
75
+ add_action( 'woocommerce_after_account_payment_methods', array( $this, 'render' ) );
76
+ add_action( 'woocommerce_after_account_payment_methods', array( $this, 'render_js' ) );
77
+
78
+ // handle payment method deletion, etc.
79
+ $this->handle_payment_method_actions();
80
+ }
81
+
82
+
83
+ /**
84
+ * Enqueue frontend CSS/JS
85
+ *
86
+ * @since 3.0.0
87
+ */
88
+ public function maybe_enqueue_styles_scripts() {
89
+
90
+ $handle = 'wc-square-payment-gateway-my-payment-methods';
91
+
92
+ // if there are tokens to display, add the custom JS
93
+ if ( $this->has_tokens ) {
94
+
95
+ wp_register_script( 'jquery-tiptip', WC()->plugin_url() . '/assets/js/jquery-tiptip/jquery.tipTip.min.js', array( 'jquery' ), WC_VERSION, true );
96
+
97
+ wp_enqueue_style( $handle, $this->get_plugin()->get_plugin_url() . '/assets/css/frontend/' . $handle . '.min.css', array( 'dashicons' ), Plugin::VERSION );
98
+
99
+ wp_enqueue_script( $handle, $this->get_plugin()->get_plugin_url() . '/assets/js/frontend/' . $handle . '.min.js', array( 'jquery-tiptip', 'jquery' ), Plugin::VERSION );
100
+ }
101
+ }
102
+
103
+
104
+ /**
105
+ * Get the the available tokens for each plugin gateway and combine them
106
+ *
107
+ * Tokens are also separated into Credit Card and eCheck-specific class members
108
+ * for convenience.
109
+ *
110
+ * @since 3.0.0
111
+ */
112
+ protected function load_tokens() {
113
+
114
+ if ( ! empty( $this->tokens ) ) {
115
+ return $this->tokens;
116
+ }
117
+
118
+ $this->credit_card_tokens = $this->echeck_tokens = array();
119
+
120
+ foreach ( $this->get_plugin()->get_gateways() as $gateway ) {
121
+
122
+ if ( ! $gateway->is_available() || ! ( $gateway->supports_tokenization() && $gateway->tokenization_enabled() ) ) {
123
+ continue;
124
+ }
125
+
126
+ foreach ( $gateway->get_payment_tokens_handler()->get_tokens( get_current_user_id() ) as $token ) {
127
+
128
+ // prevent duplicates, as some gateways will return all tokens in each each gateway
129
+ if ( isset( $this->credit_card_tokens[ $token->get_id() ] ) || isset( $this->echeck_tokens[ $token->get_id() ] ) ) {
130
+ continue;
131
+ }
132
+
133
+ if ( $token->is_credit_card() ) {
134
+
135
+ $this->credit_card_tokens[ $token->get_id() ] = $token;
136
+
137
+ }
138
+ }
139
+ }
140
+
141
+ // we don't use array_merge here since the indexes could be numeric
142
+ // and cause the indexes to be reset
143
+ $this->tokens = $this->credit_card_tokens + $this->echeck_tokens;
144
+
145
+ $this->has_tokens = ! empty( $this->tokens );
146
+
147
+ return $this->tokens;
148
+ }
149
+
150
+
151
+ /**
152
+ * Render the payment methods table.
153
+ *
154
+ * @since 3.0.0
155
+ */
156
+ public function render() {
157
+
158
+ if ( $this->has_tokens ) {
159
+
160
+ /**
161
+ * Before My Payment Methods Table Action.
162
+ *
163
+ * Fired before the My Payment Methods table HTML is rendered.
164
+ *
165
+ * @since 3.0.0
166
+ *
167
+ * @param Payment_Gateway_My_Payment_Methods $this instance
168
+ */
169
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_before_my_payment_method_table', $this );
170
+
171
+ echo $this->get_table_html();
172
+
173
+ /**
174
+ * After My Payment Methods Table Action.
175
+ *
176
+ * Fired after the My Payment Methods table HTML is rendered.
177
+ *
178
+ * @since 3.0.0
179
+ *
180
+ * @param Payment_Gateway_My_Payment_Methods $this instance
181
+ */
182
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_after_my_payment_method_table', $this );
183
+
184
+ }
185
+ }
186
+
187
+
188
+ /**
189
+ * Renders the JavaScript.
190
+ *
191
+ * @since 3.0.0
192
+ */
193
+ public function render_js() {
194
+
195
+ $args = array(
196
+ 'id' => $this->get_plugin()->get_id(),
197
+ 'slug' => $this->get_plugin()->get_id_dasherized(),
198
+ 'has_core_tokens' => (bool) wc_get_customer_saved_methods_list( get_current_user_id() ),
199
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
200
+ 'ajax_nonce' => wp_create_nonce( 'wc_' . $this->get_plugin()->get_id() . '_save_payment_method' ),
201
+ 'i18n' => array(
202
+ 'edit_button' => esc_html__( 'Edit', 'woocommerce-square' ),
203
+ 'cancel_button' => esc_html__( 'Cancel', 'woocommerce-square' ),
204
+ 'save_error' => esc_html__( 'Oops, there was an error updating your payment method. Please try again.', 'woocommerce-square' ),
205
+ 'delete_ays' => esc_html__( 'Are you sure you want to delete this payment method?', 'woocommerce-square' ),
206
+ ),
207
+ );
208
+
209
+ /**
210
+ * Filters the payment gateway payment methods JavaScript args.
211
+ *
212
+ * @since 3.0.0
213
+ *
214
+ * @param array $args arguments
215
+ * @param Payment_Gateway_My_Payment_Methods $handler payment methods handler
216
+ */
217
+ $args = apply_filters( 'wc_payment_gateway_' . $this->get_plugin()->get_id() . '_payment_methods_js_args', $args, $this );
218
+
219
+ wc_enqueue_js( sprintf(
220
+ 'window.wc_%1$s_payment_methods_handler = new %2$s( %3$s );',
221
+ esc_js( $this->get_plugin()->get_id() ),
222
+ esc_js( $this->get_js_handler_class() ),
223
+ wp_json_encode( $args )
224
+ ) );
225
+ }
226
+
227
+
228
+ /**
229
+ * Gets the JS handler class name.
230
+ *
231
+ * Plugins can override this for their own JS implementations.
232
+ *
233
+ * @since 3.0.0
234
+ *
235
+ * @return string
236
+ */
237
+ protected function get_js_handler_class() {
238
+
239
+ return 'Square_Payment_Methods_Handler';
240
+ }
241
+
242
+ /**
243
+ * Return the table HTML
244
+ *
245
+ * @since 3.0.0
246
+ * @return string table HTML
247
+ */
248
+ public function get_table_html() {
249
+
250
+ $html = sprintf( '<table class="shop_table shop_table_responsive sv-wc-payment-gateway-my-payment-methods-table wc-%s-my-payment-methods">', sanitize_html_class( $this->get_plugin()->get_id_dasherized() ) );
251
+
252
+ $html .= $this->get_table_head_html();
253
+
254
+ $html .= $this->get_table_body_html();
255
+
256
+ $html .= '</table>';
257
+
258
+ /**
259
+ * My Payment Methods Table HTML Filter.
260
+ *
261
+ * Allow actors to modify the table HTML.
262
+ *
263
+ * @since 3.0.0
264
+ *
265
+ * @param string $html table HTML
266
+ * @param Payment_Gateway_My_Payment_Methods $this instance
267
+ */
268
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_html', $html, $this );
269
+ }
270
+
271
+
272
+ /**
273
+ * Return the table head HTML
274
+ *
275
+ * @since 3.0.0
276
+ * @return string table thead HTML
277
+ */
278
+ protected function get_table_head_html() {
279
+
280
+ $html = '<thead><tr>';
281
+
282
+ foreach ( $this->get_table_headers() as $key => $title ) {
283
+ $html .= sprintf( '<th class="sv-wc-payment-gateway-my-payment-method-table-header sv-wc-payment-gateway-payment-method-header-%1$s wc-%2$s-payment-method-%1$s"><span class="nobr">%3$s</span></th>', sanitize_html_class( $key ), sanitize_html_class( $this->get_plugin()->get_id_dasherized() ), esc_html( $title ) );
284
+ }
285
+
286
+ $html .= '</tr></thead>';
287
+
288
+ /**
289
+ * My Payment Methods Table Head HTML Filter.
290
+ *
291
+ * Allow actors to modify the table head HTML.
292
+ *
293
+ * @since 3.0.0
294
+ *
295
+ * @param string $html table head HTML
296
+ * @param Payment_Gateway_My_Payment_Methods $this instance
297
+ */
298
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_head_html', $html, $this );
299
+ }
300
+
301
+
302
+ /**
303
+ * Return the table headers
304
+ *
305
+ * @since 3.0.0
306
+ * @return array of table headers in key => Title format
307
+ */
308
+ protected function get_table_headers() {
309
+
310
+ $headers = array(
311
+ 'title' => __( 'Method', 'woocommerce-square' ),
312
+ 'details' => __( 'Details', 'woocommerce-square' ),
313
+ 'expiry' => __( 'Expires', 'woocommerce-square' ),
314
+ 'default' => __( 'Default?', 'woocommerce-square' ),
315
+ 'actions' => __( 'Actions', 'woocommerce-square' ),
316
+ );
317
+
318
+ /**
319
+ * My Payment Methods Table Headers Filter.
320
+ *
321
+ * Allow actors to modify the table headers.
322
+ *
323
+ * @since 3.0.0
324
+ * @param array $headers table headers {
325
+ * @type string $title
326
+ * @type string $expiry
327
+ * @type string $actions
328
+ * }
329
+ * @param Payment_Gateway_My_Payment_Methods $this instance
330
+ */
331
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_headers', $headers, $this );
332
+ }
333
+
334
+
335
+ /**
336
+ * Return the table body HTML
337
+ *
338
+ * @since 3.0.0
339
+ * @return string table tbody HTML
340
+ */
341
+ protected function get_table_body_html() {
342
+
343
+ $html = '<tbody>';
344
+
345
+ if ( $this->credit_card_tokens && $this->echeck_tokens ) {
346
+
347
+ $html .= sprintf(
348
+ '<tr class="sv-wc-payment-gateway-my-payment-methods-type-divider wc-%s-my-payment-methods-type-divider"><td colspan="%d">%s</td></tr>',
349
+ sanitize_html_class( $this->get_plugin()->get_id_dasherized() ),
350
+ count( $this->get_table_headers() ),
351
+ esc_html__( 'Credit/Debit Cards', 'woocommerce-square' )
352
+ );
353
+
354
+ $html .= $this->get_table_body_row_html( $this->credit_card_tokens );
355
+
356
+ $html .= sprintf(
357
+ '<tr class="sv-wc-payment-gateway-my-payment-methods-type-divider wc-%s-my-payment-methods-type-divider"><td colspan="%d">%s</td></tr>',
358
+ sanitize_html_class( $this->get_plugin()->get_id_dasherized() ),
359
+ count( $this->get_table_headers() ),
360
+ esc_html__( 'Bank Accounts', 'woocommerce-square' )
361
+ );
362
+
363
+ $html .= $this->get_table_body_row_html( $this->echeck_tokens );
364
+
365
+ } else {
366
+
367
+ $html .= $this->get_table_body_row_html( $this->tokens );
368
+ }
369
+
370
+ $html .= '</tbody>';
371
+
372
+ /**
373
+ * My Payment Methods Table Body HTML Filter.
374
+ *
375
+ * Allow actors to modify the table body HTML.
376
+ *
377
+ * @since 3.0.0
378
+ *
379
+ * @param string $html table body HTML
380
+ * @param Payment_Gateway_My_Payment_Methods $this instance
381
+ */
382
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_body_html', $html, $this );
383
+ }
384
+
385
+
386
+ /**
387
+ * Returns the table body row HTML, each row represents a single payment method.
388
+ *
389
+ * @since 3.0.0
390
+ *
391
+ * @param Payment_Gateway_Payment_Token[] $tokens token objects
392
+ * @return string table tbody > tr HTML
393
+ */
394
+ protected function get_table_body_row_html( $tokens ) {
395
+
396
+ $html = '';
397
+
398
+ // for responsive table data-title attributes
399
+ $headers = $this->get_table_headers();
400
+
401
+ foreach ( $tokens as $token ) {
402
+
403
+ $method = $this->get_table_body_row_data( $token );
404
+
405
+ $html .= sprintf(
406
+ '<tr class="sv-wc-payment-gateway-my-payment-methods-method wc-%1$s-my-payment-methods-method %2$s" data-token-id="%3$s">',
407
+ sanitize_html_class( $this->get_plugin()->get_id_dasherized() ),
408
+ $token->is_default() ? 'default' : '',
409
+ esc_attr( $token->get_id() )
410
+ );
411
+
412
+ // Display the row data in the order of the headers
413
+ foreach ( $headers as $attribute => $attribute_title ) {
414
+
415
+ $value = isset( $method[ $attribute ] ) ? $method[ $attribute ] : __( 'N/A', 'woocommerce-square' );
416
+
417
+ $html .= sprintf(
418
+ '<td class="sv-wc-payment-gateway-payment-method-%1$s wc-%2$s-payment-method-%1$s" data-title="%4$s">%3$s</td>',
419
+ sanitize_html_class( $attribute ),
420
+ sanitize_html_class( $this->get_plugin()->get_id_dasherized() ),
421
+ $value,
422
+ esc_attr( $attribute_title )
423
+ );
424
+ }
425
+
426
+ $html .= '</tr>';
427
+ }
428
+
429
+ /**
430
+ * My Payment Methods Table Row HTML Filter.
431
+ *
432
+ * Allow actors to modify the table row HTML.
433
+ *
434
+ * @since 3.0.0
435
+ *
436
+ * @param string $html table row HTML
437
+ * @param Payment_Gateway_Payment_Token[] $tokens simple array of token objects
438
+ * @param Payment_Gateway_My_Payment_Methods $this instance
439
+ */
440
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_row_html', $html, $tokens, $this );
441
+ }
442
+
443
+
444
+ /**
445
+ * Return the payment method data for a given token
446
+ *
447
+ * @since 3.0.0
448
+ *
449
+ * @param Payment_Gateway_Payment_Token $token the token object
450
+ * @return array payment method data suitable for HTML output
451
+ */
452
+ protected function get_table_body_row_data( $token ) {
453
+
454
+ $method = array(
455
+ 'title' => $this->get_payment_method_title_html( $token ),
456
+ 'default' => $this->get_payment_method_default_html( $token ),
457
+ 'details' => $this->get_payment_method_details_html( $token ),
458
+ 'actions' => $this->get_payment_method_actions_html( $token ),
459
+ );
460
+
461
+ // add the expiration date if applicable
462
+ if ( $token->get_exp_month() && $token->get_exp_year() ) {
463
+ $method['expiry'] = $this->get_payment_method_expiry_html( $token );
464
+ }
465
+
466
+ /**
467
+ * My Payment Methods Table Body Row Data Filter.
468
+ *
469
+ * Allow actors to modify the table body row data.
470
+ *
471
+ * @since 3.0.0
472
+ *
473
+ * @param array $methods {
474
+ * @type string $title payment method title
475
+ * @type string $expiry payment method expiry
476
+ * @type string $actions actions for payment method
477
+ * }
478
+ * @param array $token simple array of Payment_Gateway_Payment_Token objects
479
+ * @param Payment_Gateway_My_Payment_Methods $this instance
480
+ */
481
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_body_row_data', $method, $token, $this );
482
+ }
483
+
484
+ /**
485
+ * Get a token's payment method title HTML.
486
+ *
487
+ * @since 3.0.0
488
+ *
489
+ * @param Payment_Gateway_Payment_Token $token token object
490
+ * @return string
491
+ */
492
+ protected function get_payment_method_title_html( Payment_Gateway_Payment_Token $token ) {
493
+
494
+ $nickname = $token->get_nickname();
495
+ $title = $token->get_nickname() ? $token->get_nickname() : $token->get_type_full();
496
+
497
+ /**
498
+ * Filter a token's payment method title.
499
+ *
500
+ * @since 3.0.0
501
+ *
502
+ * @param string $title payment method title
503
+ * @param Payment_Gateway_Payment_Token $token token object
504
+ */
505
+ $title = apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_title', $title, $token, $this );
506
+
507
+ $html = '<div class="view">' . esc_html( $title ) . '</div>';
508
+
509
+ // add the edit context input
510
+ $html .= '<div class="edit" style="display:none;">';
511
+ $html .= '<input type="text" class="nickname" name="nickname" value="' . esc_html( $token->get_nickname() ) . '" placeholder="' . esc_attr( __( 'Nickname', 'woocommerce-square' ) ) . '" />';
512
+ $html .= '</div>';
513
+
514
+ /**
515
+ * Filter a token's payment method title HTML.
516
+ *
517
+ * @since 3.0.0
518
+ *
519
+ * @param string $html title HTML
520
+ * @param Payment_Gateway_Payment_Token $token token object
521
+ */
522
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_title_html', $html, $token );
523
+ }
524
+
525
+
526
+ /**
527
+ * Get a token's payment method "default" flag HTML.
528
+ *
529
+ * @since 3.0.0
530
+ *
531
+ * @param Payment_Gateway_Payment_Token $token token object
532
+ * @return string
533
+ */
534
+ protected function get_payment_method_default_html( Payment_Gateway_Payment_Token $token ) {
535
+
536
+ $html = '<div class="view">';
537
+ $html .= $token->is_default() ? '<mark class="default">' . esc_html__( 'Default', 'woocommerce-square' ) . '</mark>' : '';
538
+ $html .= '</div>';
539
+
540
+ // add the edit context input
541
+ $html .= '<div class="edit" style="display:none;">';
542
+ $html .= '<input type="checkbox" class="default" name="default" value="yes" ' . checked( true, $token->is_default(), false ) . ' />';
543
+ $html .= '</div>';
544
+
545
+ /**
546
+ * Filter a token's payment method "default" flag HTML.
547
+ *
548
+ * @since 3.0.0
549
+ *
550
+ * @param string $html "default" flag HTML
551
+ * @param Payment_Gateway_Payment_Token $token token object
552
+ */
553
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_default_html', $html, $token );
554
+ }
555
+
556
+
557
+ /**
558
+ * Gets a token's payment method details HTML.
559
+ *
560
+ * This includes the method type icon, last four digits, and "default"
561
+ * badge if applicable. Example:
562
+ *
563
+ * [icon] * * * 1234 [default]
564
+ *
565
+ * @since 3.0.0
566
+ *
567
+ * @param Payment_Gateway_Payment_Token $token token object
568
+ * @return array
569
+ */
570
+ protected function get_payment_method_details_html( Payment_Gateway_Payment_Token $token ) {
571
+
572
+ $html = '';
573
+
574
+ if ( $image_url = $token->get_image_url() ) {
575
+ $html .= sprintf( '<img src="%1$s" alt="%2$s" title="%2$s" width="40" height="25" />', esc_url( $image_url ), esc_attr( $token->get_type_full() ) );
576
+ }
577
+
578
+ if ( $last_four = $token->get_last_four() ) {
579
+ $html .= "&bull; &bull; &bull; {$last_four}";
580
+ }
581
+
582
+ /**
583
+ * Filters a token's payment method details HTML.
584
+ *
585
+ * @since 3.0.0
586
+ *
587
+ * @param string $html details HTML
588
+ * @param Payment_Gateway_Payment_Token $token token object
589
+ */
590
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_details_html', $html, $token );
591
+ }
592
+
593
+
594
+ /**
595
+ * Get a token's payment method expiration date HTML.
596
+ *
597
+ * @since 3.0.0
598
+ *
599
+ * @param Payment_Gateway_Payment_Token $token token object
600
+ * @return string
601
+ */
602
+ protected function get_payment_method_expiry_html( Payment_Gateway_Payment_Token $token ) {
603
+
604
+ $html = esc_html( $token->get_exp_date() );
605
+
606
+ // TODO: add edit support {CW 2018-01-30}
607
+
608
+ /**
609
+ * Filter a token's payment method expiration date HTML.
610
+ *
611
+ * @since 3.0.0
612
+ *
613
+ * @param string $html expiration date HTML
614
+ * @param Payment_Gateway_Payment_Token $token token object
615
+ */
616
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_expiry_html', $html, $token );
617
+ }
618
+
619
+
620
+ /**
621
+ * Get a token's payment method actions HTML.
622
+ *
623
+ * @since 3.0.0
624
+ *
625
+ * @param Payment_Gateway_Payment_Token $token token object
626
+ * @return string
627
+ */
628
+ protected function get_payment_method_actions_html( Payment_Gateway_Payment_Token $token ) {
629
+
630
+ $actions = array(
631
+ '<a href="#" class="edit-payment-method button">' . esc_html__( 'Edit', 'woocommerce-square' ) . '</a>',
632
+ '<a href="#" class="save-payment-method button" style="display:none">' . esc_html__( 'Save', 'woocommerce-square' ) . '</a>',
633
+ );
634
+
635
+ foreach ( $this->get_payment_method_actions( $token ) as $action => $details ) {
636
+
637
+ $classes = isset( $details['class'] ) ? (array) $details['class'] : array();
638
+ $attributes = isset( $details['attributes'] ) ? (array) $details['attributes'] : array();
639
+
640
+ $attributes['data-token-id'] = $token->get_id();
641
+ $attributes['data-action'] = $action;
642
+
643
+ // if the action has a tooltip set
644
+ if ( ! empty( $details['tip'] ) ) {
645
+
646
+ $classes[] = 'tip';
647
+
648
+ $attributes['title'] = $details['tip'];
649
+ }
650
+
651
+ // build the attributes
652
+ foreach ( $attributes as $attribute => $value ) {
653
+ $attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
654
+ unset( $attributes[ $attribute ] );
655
+ }
656
+
657
+ // build the button
658
+ $actions[] = sprintf(
659
+ ( in_array( 'disabled', $classes, true ) ) ? '<a class="button %2$s" %3$s>%4$s</a>' : '<a href="%1$s" class="button %2$s" %3$s>%4$s</a>',
660
+ ! empty( $details['url'] ) ? esc_url( $details['url'] ) : '#',
661
+ implode( ' ', array_map( 'sanitize_html_class', $classes ) ),
662
+ implode( ' ', $attributes ),
663
+ esc_html( $details['name'] )
664
+ );
665
+ }
666
+
667
+ $html = implode( '', $actions );
668
+
669
+ /**
670
+ * Filters a token's payment method actions HTML.
671
+ *
672
+ * @since 3.0.0
673
+ *
674
+ * @param string $html actions HTML
675
+ * @param Payment_Gateway_Payment_Token $token token object
676
+ */
677
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_actions_html', $html, $token );
678
+ }
679
+
680
+
681
+ /**
682
+ * Gets the actions for the given payment method token.
683
+ *
684
+ * @since 3.0.0
685
+ *
686
+ * @param Payment_Gateway_Payment_Token $token token object
687
+ * @return array
688
+ */
689
+ protected function get_payment_method_actions( $token ) {
690
+
691
+ $actions = array(
692
+ 'delete' => __( 'Delete', 'woocommerce-square' ),
693
+ );
694
+
695
+ $plugin_slug = $this->get_plugin()->get_id_dasherized();
696
+
697
+ foreach ( $actions as $action => $label ) {
698
+
699
+ $url = add_query_arg( array(
700
+ "wc-{$plugin_slug}-token" => $token->get_id(),
701
+ "wc-{$plugin_slug}-action" => $action,
702
+ ) );
703
+
704
+ $actions[ $action ] = array(
705
+ 'name' => $label,
706
+ 'url' => wp_nonce_url( $url, "wc-{$plugin_slug}-token-action" ),
707
+ 'class' => "{$action}-payment-method",
708
+ );
709
+ }
710
+
711
+ /**
712
+ * My Payment Methods Table Method Actions Filter.
713
+ *
714
+ * Allow actors to modify the table method actions.
715
+ *
716
+ * @since 3.0.0
717
+ *
718
+ * @param $actions array {
719
+ * @type string $url action URL
720
+ * @type string $class action button class
721
+ * @type string $name action button name
722
+ * }
723
+ * @param Payment_Gateway_Payment_Token $token
724
+ * @param Payment_Gateway_My_Payment_Methods $this instance
725
+ */
726
+ return apply_filters( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_table_method_actions', $actions, $token, $this );
727
+ }
728
+
729
+
730
+ /** Payment Method actions ************************************************/
731
+
732
+
733
+ /**
734
+ * Saves a payment method via AJAX.
735
+ *
736
+ * @internal
737
+ *
738
+ * @since 3.0.0
739
+ */
740
+ public function ajax_save_payment_method() {
741
+
742
+ check_ajax_referer( 'wc_' . $this->get_plugin()->get_id() . '_save_payment_method', 'nonce' );
743
+
744
+ try {
745
+
746
+ $this->load_tokens();
747
+
748
+ $token_id = Square_Helper::get_post( 'token_id' );
749
+
750
+ if ( empty( $this->tokens[ $token_id ] ) || ! $this->tokens[ $token_id ] instanceof Payment_Gateway_Payment_Token ) {
751
+ throw new \Exception( 'Invalid token ID' );
752
+ }
753
+
754
+ $user_id = get_current_user_id();
755
+ $token = $this->tokens[ $token_id ];
756
+ $gateway = $this->get_plugin()->get_gateway_from_token( $user_id, $token );
757
+
758
+ // bail if the gateway or token couldn't be found for this user
759
+ if ( ! $gateway || ! $gateway->get_payment_tokens_handler()->user_has_token( $user_id, $token ) ) {
760
+ throw new \Exception( 'Invalid token' );
761
+ }
762
+
763
+ $data = array();
764
+
765
+ parse_str( Square_Helper::get_post( 'data' ), $data );
766
+
767
+ // set the data
768
+ $token = $this->save_token_data( $token, $data );
769
+
770
+ // use the handler so other methods don't remain default
771
+ if ( $token->is_default() ) {
772
+ $gateway->get_payment_tokens_handler()->set_default_token( $user_id, $token );
773
+ }
774
+
775
+ // persist the data
776
+ $gateway->get_payment_tokens_handler()->update_token( $user_id, $token );
777
+
778
+ wp_send_json_success( array(
779
+ 'html' => $this->get_table_body_row_html( array( $token ) ),
780
+ 'is_default' => $token->is_default(),
781
+ 'nonce' => wp_create_nonce( 'wc_' . $this->get_plugin()->get_id() . '_save_payment_method' ),
782
+ ) );
783
+
784
+ } catch ( \Exception $e ) {
785
+
786
+ wp_send_json_error( $e->getMessage() );
787
+ }
788
+ }
789
+
790
+
791
+ /**
792
+ * Saves data to a token.
793
+ *
794
+ * Gateways can override this to set their own data if they add custom Edit
795
+ * fields. Note that this does not persist the data to the db, but only sets
796
+ * it for the object.
797
+ *
798
+ * @since 3.0.0
799
+ *
800
+ * @param Payment_Gateway_Payment_Token $token token object
801
+ * @param array $data {
802
+ * new data to store for the token
803
+ *
804
+ * @type string $nickname method nickname
805
+ * @type string $default whether the method should be set as default
806
+ * }
807
+ * @return Payment_Gateway_Payment_Token
808
+ */
809
+ protected function save_token_data( Payment_Gateway_Payment_Token $token, array $data ) {
810
+
811
+ $raw_nickname = ! empty( $data['nickname'] ) ? $data['nickname'] : '';
812
+ $clean_nickname = wc_clean( $raw_nickname );
813
+
814
+ // only set the nickname if there is a clean value, or it was deliberately cleared
815
+ if ( $clean_nickname || ! $raw_nickname ) {
816
+ $token->set_nickname( $clean_nickname );
817
+ }
818
+
819
+ $token->set_default( isset( $data['default'] ) && 'yes' === $data['default'] );
820
+
821
+ return $token;
822
+ }
823
+
824
+
825
+ /**
826
+ * Handle payment methods actions, e.g. deleting a payment method or setting
827
+ * one as default
828
+ *
829
+ * @since 3.0.0
830
+ */
831
+ public function handle_payment_method_actions() {
832
+
833
+ if ( ! $this->has_tokens ) {
834
+ return;
835
+ }
836
+
837
+ $token = isset( $_GET[ 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token' ] ) ? trim( $_GET[ 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token' ] ) : '';
838
+ $action = isset( $_GET[ 'wc-' . $this->get_plugin()->get_id_dasherized() . '-action' ] ) ? $_GET[ 'wc-' . $this->get_plugin()->get_id_dasherized() . '-action' ] : '';
839
+
840
+ // process payment method actions
841
+ if ( $token && $action && ! empty( $_GET['_wpnonce'] ) && is_user_logged_in() ) {
842
+
843
+ // security check
844
+ if ( false === wp_verify_nonce( $_GET['_wpnonce'], 'wc-' . $this->get_plugin()->get_id_dasherized() . '-token-action' ) ) {
845
+
846
+ Square_Helper::wc_add_notice( esc_html__( 'Oops, you took too long, please try again.', 'woocommerce-square' ), 'error' );
847
+
848
+ $this->redirect_to_my_account();
849
+ }
850
+
851
+ // current logged in user
852
+ $user_id = get_current_user_id();
853
+
854
+ $gateway = $this->get_plugin()->get_gateway_from_token( $user_id, $token );
855
+
856
+ // couldn't find an associated gateway for that token
857
+ if ( ! is_object( $gateway ) ) {
858
+
859
+ Square_Helper::wc_add_notice( esc_html__( 'There was an error with your request, please try again.', 'woocommerce-square' ), 'error' );
860
+
861
+ $this->redirect_to_my_account();
862
+ }
863
+
864
+ switch ( $action ) {
865
+
866
+ // handle deletion
867
+ case 'delete':
868
+
869
+ if ( ! $gateway->get_payment_tokens_handler()->remove_token( $user_id, $token ) ) {
870
+
871
+ /* translators: Payment method as in a specific credit card, e-check or bank account */
872
+ Square_Helper::wc_add_notice( esc_html__( 'Error removing payment method', 'woocommerce-square' ), 'error' );
873
+
874
+ } else {
875
+
876
+ /* translators: Payment method as in a specific credit card, e-check or bank account */
877
+ Square_Helper::wc_add_notice( esc_html__( 'Payment method deleted.', 'woocommerce-square' ) );
878
+
879
+ /**
880
+ * Fires after a new payment method is deleted by a customer.
881
+ *
882
+ * @since 3.0.0
883
+ *
884
+ * @param string $token_id ID of the deleted token
885
+ * @param int $user_id user ID
886
+ */
887
+ do_action( 'wc_payment_gateway_' . $gateway->get_id() . '_payment_method_deleted', $token, $user_id );
888
+ }
889
+
890
+ break;
891
+
892
+ // custom actions
893
+ default:
894
+
895
+ /**
896
+ * My Payment Methods Custom Action.
897
+ *
898
+ * Fired when a custom action is requested for a payment method (e.g. other than delete/make default)
899
+ *
900
+ * @since 3.0.0
901
+ * @param \Payment_Gateway_My_Payment_Methods $this instance
902
+ */
903
+ do_action( 'wc_' . $this->get_plugin()->get_id() . '_my_payment_methods_action_' . sanitize_title( $action ), $this );
904
+ break;
905
+ }
906
+
907
+ $this->redirect_to_my_account();
908
+ }
909
+ }
910
+
911
+
912
+ /**
913
+ * Redirect back to the Payment Methods (WC 2.6+) or My Account page
914
+ *
915
+ * @since 3.0.0
916
+ */
917
+ protected function redirect_to_my_account() {
918
+
919
+ wp_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
920
+ exit;
921
+ }
922
+
923
+
924
+ /**
925
+ * Return the gateway plugin, primarily a convenience method to other actors
926
+ * using filters
927
+ *
928
+ * @since 3.0.0
929
+ *
930
+ * @return Payment_Gateway_Plugin
931
+ *