Anonymous
Создание секрета клиента PaymentIntent в Stripe
Сообщение
Anonymous » 05 июл 2024, 13:56
Здравствуйте, я получаю сообщение об ошибке, когда пытаюсь использовать Stripe for Pur, чтобы пользователи могли оформить подписку.
Я использую Ionic 5 Angular 14 Capacitor 5 и php в качестве серверной части. Stripe отлично реализован на PHP, потому что я использую его в других случаях.
Ошибка на консоли говорит:
Код: Выделить всё
subscription.page.ts:158 Exception during payment confirmation: IntegrationError:
Invalid value for stripe.confirmCardPayment intent secret: value should be a PaymentIntent client secret.
You specified: a SetupIntent client secret.
Это мои функции интерфейса
subscription.ts
Код: Выделить всё
import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
import { Router } from "@angular/router";
import { UserData } from 'src/app/services/user-data/user-data';
import { loadStripe, Stripe, StripeElements, StripeCardElement, StripeElementsOptions, PaymentMethod, StripeCardElementChangeEvent } from '@stripe/stripe-js';
// Custom component for Stripe card element handling (optional)
class CustomStripeCardElement {
private stripeCardElement: StripeCardElement;
paymentMethod: string | PaymentMethod;
constructor(stripeCardElement: StripeCardElement) {
this.stripeCardElement = stripeCardElement;
}
on(eventType: 'change' | 'ready' | 'focus' | 'blur' | 'escape' | 'networkschange', handler: (event: StripeCardElementChangeEvent | {}) => any): void {
(this.stripeCardElement.on as any)(eventType, handler);
}
mount(selector: string): void {
this.stripeCardElement.mount(selector);
}
}
@Component({
selector: 'app-subscription',
templateUrl: 'subscription.page.html',
styleUrls: ['subscription.page.scss'],
})
export class SubscriptionPage implements AfterViewInit {
@ViewChild('paymentElement') paymentElementRef: ElementRef;
stripe: Stripe | undefined;
elements: StripeElements | undefined;
paymentElement: StripeCardElement | CustomStripeCardElement | undefined;
clientSecret: string | undefined;
planId = 'price_1OPuphGozbMWFnurmnqgNTEu'; // Replace with your actual plan ID
customerId: string | undefined;
isPaymentElementFilled = false;
user: any = {};
email: string = '';
uid: string = '';
modalOpen: boolean = false;
cardInputFocused: boolean = false;
paymentMethod: string | PaymentMethod;
menuOpenCopyright: boolean = false;
constructor(public router: Router, public userData: UserData) {
this.user = this.userData.getUserData();
this.email = this.user.email;
}
ngAfterViewInit() {
// Fetch the clientSecret before initializing Stripe
this.userData.createCustomer(this.email).subscribe(
(customerResponse: any) => {
if (customerResponse.success) {
this.customerId = customerResponse.customer.id;
console.log('Customer created:', customerResponse.customer);
// Create SetupIntent only if necessary (e.g., for card details collection)
this.userData.createSetupIntent(this.customerId).subscribe(
(setupIntentResponse: any) => {
if (setupIntentResponse.success) {
this.clientSecret = setupIntentResponse.setupIntent.client_secret;
console.log('Setup Intent created:', setupIntentResponse.setupIntent);
// Initialize Stripe after getting clientSecret
this.initializeStripe().then(() => {
if (this.clientSecret) { // Check for valid clientSecret before creating payment element
this.createPaymentElement(this.clientSecret);
} else {
console.error('Missing clientSecret for payment element');
}
}).catch(error => {
console.error('Error initializing Stripe:', error);
});
} else {
console.error('Setup Intent Error:', setupIntentResponse.error);
}
},
(error) => console.error('Error creating SetupIntent:', error)
);
} else {
console.error('Customer Creation Error:', customerResponse.error);
}
},
(error) => console.error('Error creating customer:', error)
);
}
async initializeStripe() {
const stripePromise = loadStripe('pk_test_51HiSUoGozbMWFnurWW3azSXFZV47mcnH8p4MQG6HvbHuszrDPvUFYuq15TbVqZujcJNv4CSHSqkAkFm3pRk7nwod00iHrTzUTS'); // Replace with your publishable key
this.stripe = await stripePromise;
}
createPaymentElement(clientSecret: string) {
if (!this.stripe) {
console.error('Stripe is not initialized.');
return;
}
this.elements = this.stripe.elements({ clientSecret: clientSecret });
const paymentElementOptions = {};
const stripeCardElement = this.elements.create('payment', paymentElementOptions) as unknown as StripeCardElement;
// Choose between using the default StripeCardElement or your custom component (optional)
// this.paymentElement = stripeCardElement;
this.paymentElement = new CustomStripeCardElement(stripeCardElement); // Use custom component for more control (optional)
this.paymentElement.on('change', (event: any) => {
this.isPaymentElementFilled = event.complete;
});
this.paymentElement.mount('#payment-element');
}
async confirmPayment() {
try {
if (!this.clientSecret || !this.paymentElement) {
console.error('Missing clientSecret or payment element');
return;
}
const { paymentIntent, error } = await this.stripe.confirmCardPayment(this.clientSecret, {
payment_method: {
card: this.paymentElement as StripeCardElement, // Cast to StripeCardElement
},
});
if (error) {
console.error('Error during payment confirmation:', error);
return;
}
if (!paymentIntent) {
console.error('No paymentIntent returned');
return;
}
console.log('Payment Intent:', paymentIntent);
// Handle successful payment (e.g., call subscribe function)
this.subscribe(paymentIntent.payment_method); // Pass payment method to subscribe
} catch (err) {
console.error('Exception during payment confirmation:', err);
}
}
subscribe(paymentMethod: string | PaymentMethod | undefined) {
let paymentMethodString: string | undefined;
if (typeof paymentMethod === 'string') {
paymentMethodString = paymentMethod;
} else if (paymentMethod && typeof paymentMethod === 'object' && paymentMethod.id) {
paymentMethodString = paymentMethod.id;
} else {
console.error('Invalid or undefined payment method:', paymentMethod);
return;
}
if (paymentMethodString) {
console.log('Creating subscription with payment method:', paymentMethodString);
this.userData.createSubscription(this.customerId, this.planId, this.clientSecret, paymentMethodString).subscribe(
(response: any) => {
if (response.success) {
console.log('Subscription created successfully:', response.subscription);
// Handle successful subscription creation (e.g., navigate to confirmation page)
} else {
console.error('Error creating subscription:', response.error);
}
},
(error: any) => console.error('HTTP error creating subscription:', error)
);
} else {
console.error('Payment method string is undefined');
}
}
службы пользовательских данных
Код: Выделить всё
createCustomer(email: string) {
const url = this.appData.getApiUrl() + 'createCustomer';
const data = this.jsonToURLEncoded({
api_signature: this.api_signature,
email: email
});
return this.http.post(url, data, { headers: this.options });
}
createSetupIntent(customerId: string) {
const url = this.appData.getApiUrl() + 'createSetupIntent';
const data = this.jsonToURLEncoded({
customerId: customerId
});
return this.http.post(url, data, { headers: this.options });
};
createSubscription(customerId: string, planId: string, clientSecret: string, paymentMethod: string) {
const url = this.appData.getApiUrl() + 'createSubscription';
const data = this.jsonToURLEncoded({
customerId: customerId,
planId: planId,
clientSecret: clientSecret,
paymentMethod: paymentMethod, // Add the paymentMethod parameter here
});
return this.http.post(url, data, { headers: this.options });
}
функции PHP
Код: Выделить всё
function createCustomer() {
$request = \Slim\Slim::getInstance()->request();
$response['success'] = true;
$userEmail = $request->post('email');
try {
$customer = \Stripe\Customer::create([
'email' => $userEmail,
]);
$userStripeCustomerId = $customer->id;
$db = getDB();
$sql = "UPDATE users SET customer_id = :customer_id WHERE email = :email";
$stmt = $db->prepare($sql);
$stmt->bindParam(":customer_id", $userStripeCustomerId, PDO::PARAM_STR);
$stmt->bindParam(":email", $userEmail, PDO::PARAM_STR);
$stmt->execute();
$response = [
'customer' => $customer,
'success' => true,
];
} catch (\Stripe\Exception\CardException $e) {
$response = [
'error' => $e->getMessage(),
'success' => false,
];
}
echo json_encode($response);
}
function createSetupIntent() {
$request = \Slim\Slim::getInstance()->request();
$response['success'] = true;
$customerId = $request->post('customerId');
try {
$setupIntent = \Stripe\SetupIntent::create([
'customer' => $customerId,
]);
$clientSecret = $setupIntent->client_secret;
$response = [
'setupIntent' => $setupIntent,
'clientSecret' => $clientSecret,
'success' => true,
];
} catch (\Stripe\Exception\CardException $e) {
$response = [
'error' => $e->getMessage(),
'success' => false,
];
}
echo json_encode($response);
}
function createSubscription() {
$request = \Slim\Slim::getInstance()->request();
$response['success'] = true;
$customerId = $request->post('customerId');
$planId = $request->post('planId');
$paymentMethod = $request->post('paymentMethod');
try {
$subscription = \Stripe\Subscription::create([
'customer' => $customerId,
'items' => [
[
'price' => $planId,
],
],
'default_payment_method' => $paymentMethod,
]);
$response = [
'subscription' => $subscription,
'success' => true,
];
} catch (\Stripe\Exception\CardException $e) {
$response = [
'error' => $e->getMessage(),
'success' => false,
];
}
echo json_encode($response);
}
и HTML
Помощь?
Подробнее здесь:
https://stackoverflow.com/questions/787 ... -on-stripe
1720176973
Anonymous
Здравствуйте, я получаю сообщение об ошибке, когда пытаюсь использовать Stripe for Pur, чтобы пользователи могли оформить подписку. Я использую Ionic 5 Angular 14 Capacitor 5 и php в качестве серверной части. Stripe отлично реализован на PHP, потому что я использую его в других случаях. Ошибка на консоли говорит: [code]subscription.page.ts:158 Exception during payment confirmation: IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a PaymentIntent client secret. You specified: a SetupIntent client secret. [/code] Это мои функции интерфейса subscription.ts [code]import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; import { Router } from "@angular/router"; import { UserData } from 'src/app/services/user-data/user-data'; import { loadStripe, Stripe, StripeElements, StripeCardElement, StripeElementsOptions, PaymentMethod, StripeCardElementChangeEvent } from '@stripe/stripe-js'; // Custom component for Stripe card element handling (optional) class CustomStripeCardElement { private stripeCardElement: StripeCardElement; paymentMethod: string | PaymentMethod; constructor(stripeCardElement: StripeCardElement) { this.stripeCardElement = stripeCardElement; } on(eventType: 'change' | 'ready' | 'focus' | 'blur' | 'escape' | 'networkschange', handler: (event: StripeCardElementChangeEvent | {}) => any): void { (this.stripeCardElement.on as any)(eventType, handler); } mount(selector: string): void { this.stripeCardElement.mount(selector); } } @Component({ selector: 'app-subscription', templateUrl: 'subscription.page.html', styleUrls: ['subscription.page.scss'], }) export class SubscriptionPage implements AfterViewInit { @ViewChild('paymentElement') paymentElementRef: ElementRef; stripe: Stripe | undefined; elements: StripeElements | undefined; paymentElement: StripeCardElement | CustomStripeCardElement | undefined; clientSecret: string | undefined; planId = 'price_1OPuphGozbMWFnurmnqgNTEu'; // Replace with your actual plan ID customerId: string | undefined; isPaymentElementFilled = false; user: any = {}; email: string = ''; uid: string = ''; modalOpen: boolean = false; cardInputFocused: boolean = false; paymentMethod: string | PaymentMethod; menuOpenCopyright: boolean = false; constructor(public router: Router, public userData: UserData) { this.user = this.userData.getUserData(); this.email = this.user.email; } ngAfterViewInit() { // Fetch the clientSecret before initializing Stripe this.userData.createCustomer(this.email).subscribe( (customerResponse: any) => { if (customerResponse.success) { this.customerId = customerResponse.customer.id; console.log('Customer created:', customerResponse.customer); // Create SetupIntent only if necessary (e.g., for card details collection) this.userData.createSetupIntent(this.customerId).subscribe( (setupIntentResponse: any) => { if (setupIntentResponse.success) { this.clientSecret = setupIntentResponse.setupIntent.client_secret; console.log('Setup Intent created:', setupIntentResponse.setupIntent); // Initialize Stripe after getting clientSecret this.initializeStripe().then(() => { if (this.clientSecret) { // Check for valid clientSecret before creating payment element this.createPaymentElement(this.clientSecret); } else { console.error('Missing clientSecret for payment element'); } }).catch(error => { console.error('Error initializing Stripe:', error); }); } else { console.error('Setup Intent Error:', setupIntentResponse.error); } }, (error) => console.error('Error creating SetupIntent:', error) ); } else { console.error('Customer Creation Error:', customerResponse.error); } }, (error) => console.error('Error creating customer:', error) ); } async initializeStripe() { const stripePromise = loadStripe('pk_test_51HiSUoGozbMWFnurWW3azSXFZV47mcnH8p4MQG6HvbHuszrDPvUFYuq15TbVqZujcJNv4CSHSqkAkFm3pRk7nwod00iHrTzUTS'); // Replace with your publishable key this.stripe = await stripePromise; } createPaymentElement(clientSecret: string) { if (!this.stripe) { console.error('Stripe is not initialized.'); return; } this.elements = this.stripe.elements({ clientSecret: clientSecret }); const paymentElementOptions = {}; const stripeCardElement = this.elements.create('payment', paymentElementOptions) as unknown as StripeCardElement; // Choose between using the default StripeCardElement or your custom component (optional) // this.paymentElement = stripeCardElement; this.paymentElement = new CustomStripeCardElement(stripeCardElement); // Use custom component for more control (optional) this.paymentElement.on('change', (event: any) => { this.isPaymentElementFilled = event.complete; }); this.paymentElement.mount('#payment-element'); } async confirmPayment() { try { if (!this.clientSecret || !this.paymentElement) { console.error('Missing clientSecret or payment element'); return; } const { paymentIntent, error } = await this.stripe.confirmCardPayment(this.clientSecret, { payment_method: { card: this.paymentElement as StripeCardElement, // Cast to StripeCardElement }, }); if (error) { console.error('Error during payment confirmation:', error); return; } if (!paymentIntent) { console.error('No paymentIntent returned'); return; } console.log('Payment Intent:', paymentIntent); // Handle successful payment (e.g., call subscribe function) this.subscribe(paymentIntent.payment_method); // Pass payment method to subscribe } catch (err) { console.error('Exception during payment confirmation:', err); } } subscribe(paymentMethod: string | PaymentMethod | undefined) { let paymentMethodString: string | undefined; if (typeof paymentMethod === 'string') { paymentMethodString = paymentMethod; } else if (paymentMethod && typeof paymentMethod === 'object' && paymentMethod.id) { paymentMethodString = paymentMethod.id; } else { console.error('Invalid or undefined payment method:', paymentMethod); return; } if (paymentMethodString) { console.log('Creating subscription with payment method:', paymentMethodString); this.userData.createSubscription(this.customerId, this.planId, this.clientSecret, paymentMethodString).subscribe( (response: any) => { if (response.success) { console.log('Subscription created successfully:', response.subscription); // Handle successful subscription creation (e.g., navigate to confirmation page) } else { console.error('Error creating subscription:', response.error); } }, (error: any) => console.error('HTTP error creating subscription:', error) ); } else { console.error('Payment method string is undefined'); } } [/code] службы пользовательских данных [code]createCustomer(email: string) { const url = this.appData.getApiUrl() + 'createCustomer'; const data = this.jsonToURLEncoded({ api_signature: this.api_signature, email: email }); return this.http.post(url, data, { headers: this.options }); } createSetupIntent(customerId: string) { const url = this.appData.getApiUrl() + 'createSetupIntent'; const data = this.jsonToURLEncoded({ customerId: customerId }); return this.http.post(url, data, { headers: this.options }); }; createSubscription(customerId: string, planId: string, clientSecret: string, paymentMethod: string) { const url = this.appData.getApiUrl() + 'createSubscription'; const data = this.jsonToURLEncoded({ customerId: customerId, planId: planId, clientSecret: clientSecret, paymentMethod: paymentMethod, // Add the paymentMethod parameter here }); return this.http.post(url, data, { headers: this.options }); } [/code] функции PHP [code]function createCustomer() { $request = \Slim\Slim::getInstance()->request(); $response['success'] = true; $userEmail = $request->post('email'); try { $customer = \Stripe\Customer::create([ 'email' => $userEmail, ]); $userStripeCustomerId = $customer->id; $db = getDB(); $sql = "UPDATE users SET customer_id = :customer_id WHERE email = :email"; $stmt = $db->prepare($sql); $stmt->bindParam(":customer_id", $userStripeCustomerId, PDO::PARAM_STR); $stmt->bindParam(":email", $userEmail, PDO::PARAM_STR); $stmt->execute(); $response = [ 'customer' => $customer, 'success' => true, ]; } catch (\Stripe\Exception\CardException $e) { $response = [ 'error' => $e->getMessage(), 'success' => false, ]; } echo json_encode($response); } function createSetupIntent() { $request = \Slim\Slim::getInstance()->request(); $response['success'] = true; $customerId = $request->post('customerId'); try { $setupIntent = \Stripe\SetupIntent::create([ 'customer' => $customerId, ]); $clientSecret = $setupIntent->client_secret; $response = [ 'setupIntent' => $setupIntent, 'clientSecret' => $clientSecret, 'success' => true, ]; } catch (\Stripe\Exception\CardException $e) { $response = [ 'error' => $e->getMessage(), 'success' => false, ]; } echo json_encode($response); } function createSubscription() { $request = \Slim\Slim::getInstance()->request(); $response['success'] = true; $customerId = $request->post('customerId'); $planId = $request->post('planId'); $paymentMethod = $request->post('paymentMethod'); try { $subscription = \Stripe\Subscription::create([ 'customer' => $customerId, 'items' => [ [ 'price' => $planId, ], ], 'default_payment_method' => $paymentMethod, ]); $response = [ 'subscription' => $subscription, 'success' => true, ]; } catch (\Stripe\Exception\CardException $e) { $response = [ 'error' => $e->getMessage(), 'success' => false, ]; } echo json_encode($response); } [/code] и HTML [code] Subscribe for 3,99€/month [/code] Помощь? Подробнее здесь: [url]https://stackoverflow.com/questions/78710982/creating-paymentintent-client-secret-on-stripe[/url]