134 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
{
 | 
						|
  const paypalErrors = document.querySelector("#paypal-errors");
 | 
						|
  const buttonsContainer = document.getElementById('paypal-button-container');
 | 
						|
 | 
						|
 | 
						|
  function resultMessage(msg) {
 | 
						|
    paypalErrors.innerHTML = `${msg}`;
 | 
						|
  }
 | 
						|
 | 
						|
  const GAME_NAME = document.querySelector('input[id="game-name"]').value;
 | 
						|
  const GAME_ID = parseInt(document.querySelector('input[id="game-id"]').value);
 | 
						|
  // const CSRF_TOKEN = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
 | 
						|
 | 
						|
  window.paypal
 | 
						|
    .Buttons({
 | 
						|
      style: {
 | 
						|
        shape: "rect",
 | 
						|
        layout: "vertical",
 | 
						|
        color: "gold",
 | 
						|
        label: "paypal",
 | 
						|
      },
 | 
						|
      onInit: function (data, actions) {
 | 
						|
        buttonsContainer.style.display = 'block';
 | 
						|
      },
 | 
						|
      async createOrder() {
 | 
						|
        paypalErrors.textContent = '';
 | 
						|
        try {
 | 
						|
          const response = await fetch("/api/orders", {
 | 
						|
            method: "POST",
 | 
						|
            headers: {
 | 
						|
              "Content-Type": "application/json",
 | 
						|
              // 'X-CSRF-TOKEN': CSRF_TOKEN,
 | 
						|
            },
 | 
						|
            // use the "body" param to optionally pass additional order information
 | 
						|
            // like product ids and quantities
 | 
						|
            body: JSON.stringify({
 | 
						|
              payee: {
 | 
						|
                merchant_id: "YUD9N2F66QX7A",
 | 
						|
              },
 | 
						|
              cart: [{
 | 
						|
                description: GAME_NAME,
 | 
						|
                quantity: "1",
 | 
						|
                category: "DIGITAL_GOODS",
 | 
						|
                unit_amount: {
 | 
						|
                  currency_code: "USD",
 | 
						|
                  value: "5.00"
 | 
						|
                },
 | 
						|
              },],
 | 
						|
            }),
 | 
						|
          });
 | 
						|
 | 
						|
          const orderData = await response.json();
 | 
						|
 | 
						|
          if (orderData.id) {
 | 
						|
            return orderData.id;
 | 
						|
          }
 | 
						|
          const errorDetail = orderData?.details?.[0];
 | 
						|
          const errorMessage = errorDetail ?
 | 
						|
            `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})` :
 | 
						|
            JSON.stringify(orderData);
 | 
						|
 | 
						|
          throw new Error(errorMessage);
 | 
						|
        } catch (error) {
 | 
						|
          console.error(error);
 | 
						|
          resultMessage(`Could not initiate PayPal Checkout.`);
 | 
						|
        }
 | 
						|
      },
 | 
						|
      async onApprove(data, actions) {
 | 
						|
        try {
 | 
						|
          const response = await fetch(`/api/orders/${data.orderID}/capture`, {
 | 
						|
            method: "POST",
 | 
						|
            headers: {
 | 
						|
              // 'X-CSRF-TOKEN': CSRF_TOKEN,
 | 
						|
              "Content-Type": "application/x-www-form-urlencoded"
 | 
						|
            },
 | 
						|
            body: `game_id=${GAME_ID}`
 | 
						|
          });
 | 
						|
 | 
						|
          const orderData = await response.json();
 | 
						|
          // Three cases to handle:
 | 
						|
          //   (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
 | 
						|
          //   (2) Other non-recoverable errors -> Show a failure message
 | 
						|
          //   (3) Successful transaction -> Show confirmation or thank you message
 | 
						|
 | 
						|
          const errorDetail = orderData?.details?.[0];
 | 
						|
 | 
						|
          if (errorDetail?.issue === "INSTRUMENT_DECLINED") {
 | 
						|
            // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
 | 
						|
            // recoverable state, per
 | 
						|
            // https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
 | 
						|
            return actions.restart();
 | 
						|
          } else if (errorDetail) {
 | 
						|
            // (2) Other non-recoverable errors -> Show a failure message
 | 
						|
            throw new Error(`${errorDetail.description} (${orderData.debug_id})`);
 | 
						|
          } else if (!orderData.purchase_units) {
 | 
						|
            throw new Error(JSON.stringify(orderData));
 | 
						|
          } else {
 | 
						|
            // (3) Successful transaction -> Show confirmation or thank you message
 | 
						|
            // Or go to another URL:  actions.redirect('thank_you.html');
 | 
						|
            const transaction =
 | 
						|
              orderData?.purchase_units?.[0]?.payments?.captures?.[0] ||
 | 
						|
              orderData?.purchase_units?.[0]?.payments?.authorizations?.[0];
 | 
						|
            resultMessage(
 | 
						|
              `<b>Payment successful!</b> (Transaction ID: ${transaction.id})`
 | 
						|
            );
 | 
						|
 | 
						|
            buttonsContainer.style.display = "none";
 | 
						|
            // console.log(
 | 
						|
            //   "Capture result",
 | 
						|
            //   orderData,
 | 
						|
            //   JSON.stringify(orderData, null, 2)
 | 
						|
            // );
 | 
						|
            setTimeout(() => {
 | 
						|
              window.location.href = `/games/${GAME_ID}`;
 | 
						|
            }, 1000);
 | 
						|
          }
 | 
						|
        } catch (error) {
 | 
						|
          console.error(error);
 | 
						|
          resultMessage(
 | 
						|
            `Your transaction (Transaction ID: ${transaction.id}) could not be processed.`
 | 
						|
          );
 | 
						|
        }
 | 
						|
      },
 | 
						|
      onError: (err) => {
 | 
						|
        if (err === "Error: Detected popup close") { return; };
 | 
						|
        console.error(err);
 | 
						|
      },
 | 
						|
      onCancel: (data) => {
 | 
						|
        // Show a cancel page or return to cart
 | 
						|
        resultMessage("Payment cancelled.");
 | 
						|
      },
 | 
						|
    })
 | 
						|
    .render("#paypal-button-container");
 | 
						|
}
 |