1

I'm trying to integrate Stripe's custom payment flow following this tutorial: https://stripe.com/docs/payments/integration-builder

This is what I tried

// A reference to Stripe.js initialized with your real test publishable API key.
var stripe = Stripe("pk_test..");



 var formData = {
            'email': document.getElementById("email").value,
            'cardholder-name': document.getElementById("cardholder-name").value,
            'user_id': document.getElementById("user_id").value
        };

// Disable the button until we have Stripe set up on the page
document.querySelector("button").disabled = true;
fetch("create.php", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(formData),

})
  .then(function(result) {
    return result.json();
  })
  .then(function(data) {
    var elements = stripe.elements();

    var style = {
      base: {
        color: "#32325d",
        fontFamily: 'Arial, sans-serif',
        fontSmoothing: "antialiased",
        fontSize: "16px",
        "::placeholder": {
          color: "#32325d"
        }
      },
      invalid: {
        fontFamily: 'Arial, sans-serif',
        color: "#fa755a",
        iconColor: "#fa755a"
      }
    };

    var card = elements.create("card", { style: style });
    // Stripe injects an iframe into the DOM
    card.mount("#card-element");

    card.on("change", function (event) {
      // Disable the Pay button if there are no card details in the Element
      document.querySelector("button").disabled = event.empty;
      document.querySelector("#card-error").textContent = event.error ? event.error.message : "";
    });

    var form = document.getElementById("payment-form");
    form.addEventListener("submit", function(event) {
      event.preventDefault();
      // Complete payment when the submit button is clicked
      payWithCard(stripe, card, data.clientSecret);
    });
  });

// Calls stripe.confirmCardPayment
// If the card requires authentication Stripe shows a pop-up modal to
// prompt the user to enter authentication details without leaving your page.
var payWithCard = function(stripe, card, clientSecret) {
  loading(true);
  stripe
    .confirmCardPayment(clientSecret, {
      payment_method: {
        card: card
      }
    })
    .then(function(result) {
      if (result.error) {
        // Show error to your customer
        showError(result.error.message);
      } else {
        // The payment succeeded!
        orderComplete(result.paymentIntent.id);
      }
    });
};

/* ------- UI helpers ------- */

// Shows a success message when the payment is complete
var orderComplete = function(paymentIntentId) {
  loading(false);
  document
    .querySelector(".result-message a")
    .setAttribute(
      "href",
      "https://dashboard.stripe.com/test/payments/" + paymentIntentId
    );
  document.querySelector(".result-message").classList.remove("hidden");
  document.querySelector("button").disabled = true;
};

// Show the customer the error from Stripe if their card fails to charge
var showError = function(errorMsgText) {
  loading(false);
  var errorMsg = document.querySelector("#card-error");
  errorMsg.textContent = errorMsgText;
  setTimeout(function() {
    errorMsg.textContent = "";
  }, 4000);
};

// Show a spinner on payment submission
var loading = function(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("button").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("button").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
};
<form id="payment-form">
           
    <input type="hidden" id="user_id"  value="<? echo $user_id; ?>">
  <div class="form-group">
                       
                      </div>
  <label>
      
    <input id="cardholder-name" class="field is-empty" placeholder="Cardholder Name" style="height: 50px;" />
  </label>
  <label>
    <input class="field is-empty" type="email" name="email" id="email" placeholder="Your Email" style="height: 50px;" />
    
  </label>
    <label>
      <div id="card-element" class="field form-control"><!--Stripe.js injects the Card Element--></div><br><br>
      </label>
      <button id="submit">
        <div class="spinner hidden" id="spinner"></div>
        <span id="button-text">Submit Payment</span>
      </button>
      <p id="card-error" role="alert"></p>
      <p class="result-message hidden">
        Payment succeeded, see the result in your
        <a href="" target="_blank">Stripe dashboard.</a> Refresh the page to pay again.
      </p>
    </form>

Now, the payment is going through successfully. I just don't know how to access my formData values on the server side. Here is my create.php:

require 'vendor/autoload.php';
\Stripe\Stripe::setApiKey('sk_test_...');  
header('Content-Type: application/json');

try {
  // retrieve JSON from POST body
  $json_str = file_get_contents('php://input');
  $json_obj = json_decode($json_str);

  $email = $json_obj['email'];
  
$paymentIntent = \Stripe\PaymentIntent::create([
    'amount' => 1000,
    'currency' => 'gbp',
    'description' => $user_id,
    "receipt_email" => $email,
   "payment_method_options" => [
    "card" =>   [  "installments"  => null,
                "network" => null,
                 "request_three_d_secure" => "automatic" ]
  ],
  "payment_method_types" => ["card"] ]);

  $output = [
    'clientSecret' => $paymentIntent->client_secret,
  ];
            
  echo json_encode($output);
} catch (Error $e) {
  http_response_code(500);
  echo json_encode(['error' => $e->getMessage()]);
}

The email and user_id is still not being passed and is returning empty on Stripe dashboard. But, as I said the payment is successful. But, I need to link it to a user_id, email. to use it. Please help. Thanks in advance.

Mark charlton
  • 377
  • 3
  • 15

1 Answers1

0

In the snippet you shared, $user_id and $email are not defined anywhere, only provided in the parameters.

Assuming you've confirmed the payload reaches your server as intended from the client, did you mean to set these:

$user_id = $json['user_id'];
$email = $json['email'];
Nolan H
  • 6,205
  • 1
  • 5
  • 19
  • I've amended this, still getting the same problem – Mark charlton Oct 07 '20 at 17:25
  • I feel like I'm not sending the formData array correctly or I'm not parsing the json object correctly. How can I confirm the payload reaches the server? – Mark charlton Oct 07 '20 at 17:26
  • It looks like you're already doing the right thing for accessing data posted as `application/json`: https://stackoverflow.com/a/8207498/12474862 I'd suggest adding some diagnostic logging to see what `$json_str` (and obj) is getting. – Nolan H Oct 07 '20 at 17:45