1

I have a form where a user provides a desired username/password for an account when they pay to create a membership. I am using Wordpress as the CMS to handle users/authentication.

I am using the Stripe PaymentsIntent API to process the payments.

$intent = $stripe->paymentIntents->create(
    [
        'amount' => $amount,
        'currency' => 'usd',
        'automatic_payment_methods' => ['enabled' => true],
    ]
);  

$userdata = array(
    'user_pass'             => $_POST['password'], 
    'user_login'            => $_POST['username'],  
    'user_email'            => $_POST['email'],
    'first_name'            => $_POST['first_name'], 
    'last_name'             => $_POST['last_name'], 
    'show_admin_bar_front'  => false,   
    'role'                  => $role
);
$user_id = wp_insert_user($userdata);

I want to create a Wordpress user only after the payment_intent.succeeded webhook fires -- but there's no real secure way to pass their password to Stripe and back to my server to create the user after the actual payment processed successfully.

const { error } = await stripe.confirmPayment({
        elements,
        clientSecret,
        confirmParams: {
            return_url: 'https://successurl.com/?NOSENSITIVEVARIABLES=HERE',
        },
});

The customer object in Stripe will not take passwords. I do not want to pass a password or any sensitive data using the Metadata parameter (even if I wp_password_hash() it).

I could create the user when the paymentIntent triggered, sure, but that creates users even when the payment doesn't go through successfully.

I could create a database table for pending users or a role specific to pending users on the paymentIntent.create and then validate them after the payment success, but that seems redundant.

By the time it reaches my webhook, the form fields containing the password are long gone.

When it was the Charges API, the charge went through on the server side and returned a pass/fail for me to handle logic with all of the $_POST variables still on my server. I understand why they don't do it anymore, but I'm curious how others handle webhook events on the Payment Intent API when sensitive information needs to be processed after the payment.

RCNeil
  • 8,581
  • 12
  • 43
  • 61
  • Absolutely don't send the user/pass to Stripe. I'm not familiar with what fields are available in the WP user table but I'd think the easiest solution would be probably to create a user record in a disabled state at the time the form is submitted, and then use the success hook to toggle that record to its enabled state. – Alex Howansky Jul 26 '23 at 21:05
  • 1
    WP does not really know the concept of "disabling" a user account, afaik. You could emulate it by giving a specific role or setting a flag via user meta data - and then hook into the login process, and simply reject any login, while they have that role/flag. But if your system selects/shows lists of users (other than the current one) anywhere, you might see them show up in such places, before their account is technically "active." – CBroe Jul 27 '23 at 05:59
  • I would probably just store email and result of `wp_password_hash` somewhere on your end. Then on account creation, you can read the hashed password by finding the record via the email, and update the password field in the user table record. – CBroe Jul 27 '23 at 06:01

0 Answers0