{"id":3380,"date":"2024-01-22T17:09:41","date_gmt":"2024-01-22T16:09:41","guid":{"rendered":"https:\/\/www.targetinformatica.it\/?p=3380"},"modified":"2024-02-26T11:38:36","modified_gmt":"2024-02-26T10:38:36","slug":"paypal-molly","status":"publish","type":"post","link":"https:\/\/www.targetinformatica.it\/en\/paypal-molly\/","title":{"rendered":"PayPal"},"content":{"rendered":"\n\/\/ Close 3Ds Dialog\nfunction onClose() {\n  const threedsElement = document.getElementById(&#8220;threeds&#8221;);\n  threedsElement.innerHTML = &#8220;&#8221;;\n}\n\n\/\/ Handle 3Ds Payload\nasync function onHandle3Ds(payload, orderId) {\n  const { liabilityShifted, liabilityShift } = payload;\n\n  if (liabilityShift === &#8220;POSSIBLE&#8221;) {\n    await onApproveCallback(orderId);\n  } else if (liabilityShifted === false || liabilityShifted === undefined) {\n    document.getElementById(&#8220;threeds&#8221;).innerHTML = `<Dialog open>\n        <p>You have the option to complete the payment at your own risk,\n         meaning that the liability of any chargeback has not shifted from\n          the merchant to the card issuer.<\/p>\n        <button onclick=onApproveCallback(\"${orderId}\")>Pay Now<\/button>\n        <button onclick=onClose()>Close<\/button>\n      <\/Dialog>\n    `;\n  }\n}\n\nasync function createOrderCallback() {\n  resultMessage(&#8220;&#8221;);\n  try {\n    const response = await fetch(&#8220;\/api\/orders&#8221;, {\n      method: &#8220;POST&#8221;,\n      headers: {\n        &#8220;Content-Type&#8221;: &#8220;application\/json&#8221;,\n      },\n      \/\/ use the &#8220;body&#8221; param to optionally pass additional order information\n      \/\/ like product ids and quantities\n      body: JSON.stringify({\n        cart: [\n          {\n            id: &#8220;YOUR_PRODUCT_ID&#8221;,\n            quantity: &#8220;YOUR_PRODUCT_QUANTITY&#8221;,\n          },\n        ],\n      }),\n    });\n\n    const orderData = await response.json();\n\n    if (orderData.id) {\n      return orderData.id;\n    } else {\n      const errorDetail = orderData?.details?.[0];\n      const errorMessage = errorDetail\n        ? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`\n        : JSON.stringify(orderData);\n\n      throw new Error(errorMessage);\n    }\n  } catch (error) {\n    console.error(error);\n    resultMessage(`Could not initiate PayPal Checkout&#8230;<br><br>${error}`);\n  }\n}\n\nasync function onApproveCallback(orderId) {\n  console.log(&#8220;orderId&#8221;, orderId);\n\n  const threedsElement = document.getElementById(&#8220;threeds&#8221;);\n  threedsElement.innerHTML = &#8220;&#8221;;\n\n  try {\n    const response = await fetch(`\/api\/orders\/${orderId}\/capture`, {\n      method: &#8220;POST&#8221;,\n      headers: {\n        &#8220;Content-Type&#8221;: &#8220;application\/json&#8221;,\n      },\n    });\n\n    const orderData = await response.json();\n    \/\/ Three cases to handle:\n    \/\/   (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()\n    \/\/   (2) Other non-recoverable errors -> Show a failure message\n    \/\/   (3) Successful transaction -> Show confirmation or thank you message\n\n    const transaction =\n      orderData?.purchase_units?.[0]?.payments?.captures?.[0] ||\n      orderData?.purchase_units?.[0]?.payments?.authorizations?.[0];\n    const errorDetail = orderData?.details?.[0];\n\n    \/\/ this actions.restart() behavior only applies to the Buttons component\n    if (errorDetail?.issue === &#8220;INSTRUMENT_DECLINED&#8221; &#038;&#038; !data.card &#038;&#038; actions) {\n      \/\/ (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()\n      \/\/ recoverable state, per https:\/\/developer.paypal.com\/docs\/checkout\/standard\/customize\/handle-funding-failures\/\n      return actions.restart();\n    } else if (\n      errorDetail ||\n      !transaction ||\n      transaction.status === &#8220;DECLINED&#8221;\n    ) {\n      \/\/ (2) Other non-recoverable errors -> Show a failure message\n      let errorMessage;\n      if (transaction) {\n        errorMessage = `Transaction ${transaction.status}: ${transaction.id}`;\n      } else if (errorDetail) {\n        errorMessage = `${errorDetail.description} (${orderData.debug_id})`;\n      } else {\n        errorMessage = JSON.stringify(orderData);\n      }\n\n      throw new Error(errorMessage);\n    } else {\n      \/\/ (3) Successful transaction -> Show confirmation or thank you message\n      \/\/ Or go to another URL:  actions.redirect(&#8216;thank_you.html&#8217;);\n      resultMessage(\n        `Transaction ${transaction.status}: ${transaction.id}<br><br>See console for all available details`,\n      );\n      console.log(\n        &#8220;Capture result&#8221;,\n        orderData,\n        JSON.stringify(orderData, null, 2),\n      );\n    }\n  } catch (error) {\n    console.error(error);\n    resultMessage(\n      `Sorry, your transaction could not be processed&#8230;<br><br>${error}`,\n    );\n  }\n}\n\nwindow.paypal\n  .Buttons({\n    style: {\n      shape: &#8220;pill&#8221;,\n      layout: &#8220;vertical&#8221;,\n    },\n    createOrder: createOrderCallback,\n    onApprove: (data) => onApproveCallback(data.orderID),\n  })\n  .render(&#8220;#paypal-button-container&#8221;);\n\n\/\/ Example function to show a result to the user. Your site&#8217;s UI library can be used instead.\nfunction resultMessage(message) {\n  const container = document.querySelector(&#8220;#result-message&#8221;);\n  container.innerHTML = message;\n}\n\n\/\/ If this returns false or the card fields aren&#8217;t visible, see Step #1.\nif (window.paypal.HostedFields.isEligible()) {\n  let orderId;\n  \/\/ Renders card fields\n  window.paypal.HostedFields.render({\n    \/\/ Call your server to set up the transaction\n    createOrder: async (data, actions) => {\n      orderId = await createOrderCallback(data, actions);\n      return orderId;\n    },\n    styles: {\n      &#8220;.valid&#8221;: {\n        color: &#8220;green&#8221;,\n      },\n      &#8220;.invalid&#8221;: {\n        color: &#8220;red&#8221;,\n      },\n    },\n    fields: {\n      number: {\n        selector: &#8220;#card-number&#8221;,\n        placeholder: &#8220;4111 1111 1111 1111&#8221;,\n      },\n      cvv: {\n        selector: &#8220;#cvv&#8221;,\n        placeholder: &#8220;123&#8221;,\n      },\n      expirationDate: {\n        selector: &#8220;#expiration-date&#8221;,\n        placeholder: &#8220;MM\/YY&#8221;,\n      },\n    },\n  }).then((cardFields) => {\n    document\n      .querySelector(&#8220;#card-form&#8221;)\n      .addEventListener(&#8220;submit&#8221;, async (event) => {\n        event.preventDefault();\n        try {\n          const { value: cardHolderName } =\n            document.getElementById(&#8220;card-holder-name&#8221;);\n          const { value: streetAddress } = document.getElementById(\n            &#8220;card-billing-address-street&#8221;,\n          );\n          const { value: extendedAddress } = document.getElementById(\n            &#8220;card-billing-address-unit&#8221;,\n          );\n          const { value: region } = document.getElementById(\n            &#8220;card-billing-address-state&#8221;,\n          );\n          const { value: locality } = document.getElementById(\n            &#8220;card-billing-address-city&#8221;,\n          );\n          const { value: postalCode } = document.getElementById(\n            &#8220;card-billing-address-zip&#8221;,\n          );\n          const { value: countryCodeAlpha2 } = document.getElementById(\n            &#8220;card-billing-address-country&#8221;,\n          );\n\n          const payload = await cardFields.submit({\n            cardHolderName,\n            contingencies: [&#8220;SCA_ALWAYS&#8221;],\n            billingAddress: {\n              streetAddress,\n              extendedAddress,\n              region,\n              locality,\n              postalCode,\n              countryCodeAlpha2,\n            },\n          });\n\n          await onHandle3Ds(payload, orderId);\n        } catch (error) {\n          alert(&#8220;Payment could not be captured! &#8221; + JSON.stringify(error));\n        }\n      });\n  });\n} else {\n  \/\/ Hides card fields if the merchant isn&#8217;t eligible\n  document.querySelector(&#8220;#card-form&#8221;).style = &#8220;display: none&#8221;;\n}\n","protected":false},"excerpt":{"rendered":"<p>Available for all authorized users, a new version of GD Vending Software Solutions, which introduces, among others, the following improvements<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3380","post","type-post","status-publish","format-standard","hentry","category-senza-categoria"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/posts\/3380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/comments?post=3380"}],"version-history":[{"count":10,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/posts\/3380\/revisions"}],"predecessor-version":[{"id":3441,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/posts\/3380\/revisions\/3441"}],"wp:attachment":[{"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/media?parent=3380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/categories?post=3380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.targetinformatica.it\/en\/wp-json\/wp\/v2\/tags?post=3380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}