#nikolay_code

1 messages · Page 1 of 1 (latest)

sly salmonBOT
#

👋 Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1381623727808053260

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

ionic sequoia
hollow valve
#

Hi, what integration guide are you following?

ionic sequoia
hollow valve
ionic sequoia
#

payment_intent.created
Inspect event detail in Workbench
Event data
{
"id": "pi_3RXmsn1VlpCPYqMR1XPGDNdO",
"object": "payment_intent",
"last_payment_error": null,
"livemode": false,
"next_action": null,
"status": "requires_payment_method",
"amount": 100,
"amount_capturable": 0,
"amount_details": {
"tip": {
}
},
"amount_received": 0,
"application": null,
"application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"client_secret": "pi_3RXmsn1VlpCPYqMR1XPGDNdO_secret_AnSIDC0U9kZncFfuKPkSJBsR0",
"confirmation_method": "automatic",
"created": 1749403185,
"currency": "gbp",
"customer": "cus_SSiJPCeSwTyZqd",
"description": "Subscription creation",
"latest_charge": null,
"metadata": {
},
"on_behalf_of": null,
"payment_method": null,
"payment_method_configuration_details": null,
"payment_method_options": {
"card": {
"installments": null,
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card"
],
"processing": null,
"receipt_email": null,
"review": null,
"setup_future_usage": "off_session",
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"transfer_data": null,
"transfer_group": null
}

#

are you still there?

hollow valve
#

If you look at the status of the payment intent, you can see that it requires confirmation: https://dashboard.stripe.com/test/events/evt_3RXmsn1VlpCPYqMR1qHA8akc

We document this here: https://docs.stripe.com/billing/subscriptions/build-subscriptions?platform=web&ui=elements#create-subscription

On the backend, create the subscription with status incomplete using payment_behavior=default_incomplete. Then, return the client_secret from the subscription’s first payment intent to the frontend to complete payment by expanding the confirmation_secret on the latest invoice of the subscription.

ionic sequoia
#

Ive already done this here in the payments-api.php:

// 5) Create subscription (with payment_settings)
try {
error_log("ℹ️ Creating subscription for customer {$customer->id} with PM={$pmId}");
$subscription = \Stripe\Subscription::create( [
'customer' => $customer->id,
'items' => [ [ 'price' => $plan ] ],
'payment_behavior' => 'default_incomplete',
'collection_method' => 'charge_automatically',
'default_payment_method' => $pmId,
'payment_settings' => [
'payment_method_types' => ['card'],
'save_default_payment_method' => 'on_subscription',
],
'expand' => [ 'latest_invoice.payment_intent' ],
'metadata' => $metadata,
], [
'idempotency_key' => $idempotencyKey,
] );
error_log("✅ Subscription created: id={$subscription->id}, status={$subscription->status}");
error_log("ℹ️ Subscription.default_payment_method: " . ($subscription->default_payment_method ?? 'n/a'));
if ( isset( $subscription->default_payment_method ) && $subscription->default_payment_method === $pmId ) {
error_log("✅ PM {$pmId} correctly set as Subscription.default_payment_method");
} else {
error_log("❌ PM mismatch on Subscription. Expected {$pmId}, got " . print_r($subscription->default_payment_method, true));
}
} catch ( \Exception $e ) {
error_log("❌ Subscription creation failed: " . $e->getMessage() );
wp_send_json_error( [ 'message' => 'Subscription failed' ] );
error_log('---- payments-api.php END [subscription_fail] ----');
exit;
}

#

i then return client secret heree:

// 8) Respond to frontend (always return client_secret + requires_action)
error_log('ℹ️ Responding with payment_intent_client_secret and requires_action flags');
wp_send_json_success( [
'payment_intent_client_secret' => $pi->client_secret,
'requires_action' => $pi->status === 'requires_action',
] );
error_log('---- payments-api.php END [response] ----');
exit;

hollow valve
ionic sequoia
#

which part, please could you be a bit more specific as this confers to the entirety of the process, which exact part didnt i follow?

hollow valve
ionic sequoia
#

No, but im using unified elements, i would like to keep the individual card elements to fit the UI:

            <h3 class="bhd-payment-title">PAYMENT DETAILS</h3>
          </div>

          <div class="bhd-form-fields">

            <!-- Name on Card -->
            <div class="bhd-form-group">
              <label for="cardName" class="bhd-label">Card Name</label>
              <input
                type="text"
                id="cardName"
                name="cardName"
                placeholder="John Smith"
                required
                class="bhd-input"
              />
              <span class="error-message">Please enter the name on your card</span>
            </div>

            <!-- Card Number -->
            <div class="bhd-form-group">
              <label for="card-number" class="bhd-label">Card Number</label>
              <div id="card-number" class="bhd-input"></div>
            </div>

            <!-- Expiry Date -->
            <div class="bhd-form-group">
              <label for="card-expiry" class="bhd-label">Expiry Date</label>
              <div id="card-expiry" class="bhd-input"></div>
            </div>

            <!-- CVC -->
            <div class="bhd-form-group">
              <label for="card-cvc" class="bhd-label">CVC</label>
              <div id="card-cvc" class="bhd-input"></div>
            </div>

            <!-- Combined error display -->
            <div id="card-errors" class="error-message" role="alert"></div>

          </div>
        </div>
hollow valve
#

The Card Element is a legacy integration with significantly less functionality than Payment Element. Stripe strongly recommends using the Payment Element to accept payments of all kinds, including card payments.

ionic sequoia
hollow valve
#

I explained it here: The reason behind using default_incomplete behavior is that it awaits explicit confirmation of the invoice's payment intent.

To confirm this, you can omit the payment behavior and try making a new subscription creation request

ionic sequoia
#

afk, thank you for the time being

hollow valve
#

Sure

sly salmonBOT
strong tiger
#

Hi there 👋 jumping in as my teammate needs to step away. Can you help me understand where your process stops working as expected; are you encountering error messages being thrown when you step through it?

I also see you're using our newest API version, in which case payment_intent is no longer a valid field on an Invoice object.
https://docs.stripe.com/changelog/basil/2025-03-31/add-support-for-multiple-partial-payments-on-invoices#use-for-payment-element-integrations
Instead you'll want to use the confirmation_secret on the Invoice object:
https://docs.stripe.com/api/invoices/object#invoice_object-confirmation_secret

Your code above that expands latest_invoice.payment_intent likely isn't working as you're expecting.