Код: Выделить всё
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,
StripeElement,
StripeCardNumberElement,
PaymentMethod,
StripeCardElementChangeEvent,
} from '@stripe/stripe-js';
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;
elements: StripeElements;
paymentElement: StripeCardElement | StripeCardNumberElement | CustomStripeCardElement;
clientSecret: string;
planId = 'price_1OPuphGozbMWFnurmxxxxxx';
customerId: any;
isPaymentElementFilled: boolean = false;
appearance: StripeElementsOptions['appearance'] = {
theme: 'stripe',
variables: {
colorPrimary: '#0570de',
colorBackground: '#ffffff',
colorText: '#30313d',
colorDanger: '#df1b41',
fontFamily: 'Ideal Sans, system-ui, sans-serif',
spacingUnit: '2px',
borderRadius: '4px',
// Define other custom styling variables as needed
},
};
menuOpenCopyright: boolean = false;
user: any = {};
email: string = '';
uid: string = '';
modalOpen: boolean = false;
cardInputFocused: boolean = false;
paymentMethod: string | PaymentMethod;
constructor(
public router: Router,
public userData: UserData,
) {
this.user = this.userData.getUserData();
this.uid = this.user.uid;
this.email = this.user.email;
this.clientSecret
}
ngAfterViewInit() {
this.userData.createCustomer(this.email).subscribe((customerResponse: any) => {
if (customerResponse.success) {
this.customerId = customerResponse.customer.id;
console.log('Customer created:', customerResponse.customer);
this.userData.createSetupIntent(this.customerId).subscribe((setupIntentResponse: any) => {
if (setupIntentResponse.success) {
this.clientSecret = setupIntentResponse.setupIntent.client_secret;
// Initialize Stripe after getting clientSecret
this.initializeStripe().then(() => {
// Once Stripe is initialized, create the payment element
this.createPaymentElement(this.clientSecret);
// Create Google Pay button after initializing Stripe
this.createGooglePayButton();
}).catch(error => {
console.error('Error initializing Stripe:', error);
});
} else {
console.error(setupIntentResponse.error);
}
});
} else {
console.error(customerResponse.error);
}
});
}
async initializeStripe() {
const stripePromise = loadStripe('pk_test_51HiSUoGozbMWFnurWW3azSXFZV47mcnH8p4MQG6HvbHuszrDPvUFYuq15TbVqZujcJNv4CSHSqkAkFm3pRk7nwoxxxxxxxx');
this.stripe = await stripePromise;
}
createPaymentElement(clientSecret) {
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;
this.paymentElement = new CustomStripeCardElement(stripeCardElement);
this.paymentElement.on('change', (event: any) => {
this.isPaymentElementFilled = event.complete;
});
this.paymentElement.on('networkschange', (event: any) => {
});
this.paymentElement.mount('#payment-element');
}
async confirmPayment() {
const { setupIntent, error } = await this.stripe.confirmCardSetup(this.clientSecret, {
payment_method: {
card: this.paymentElement as StripeCardElement,
billing_details: {
email: this.email,
},
},
});
console.log('Payment Method:', setupIntent.payment_method );
if (error) {
console.error(error);
} else if (setupIntent.status === 'succeeded') {
console.log('Payment succeeded:', setupIntent);
const paymentMethod = setupIntent.payment_method;
this.paymentMethod = paymentMethod;
console.log('Payment Method:', this.paymentMethod );
this.subscribe(paymentMethod);
}
}
async subscribe(paymentMethod: string | PaymentMethod) {
const paymentMethodString = paymentMethod as string;
console.log(paymentMethodString);
this.userData.createSubscription(this.customerId, this.planId, this.clientSecret, paymentMethodString).subscribe((subscriptionResponse: any) => {
if (subscriptionResponse.success) {
console.log('Subscription successful:', subscriptionResponse.subscription);
} else {
console.error(subscriptionResponse.error);
}
});
}
Код: Выделить всё
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 });
}
Код: Выделить всё
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);
}
customerId: cus_QR72U2UAixxxx
planId : цена_1OPuphGozbMWFnurmxxxxxx
clientSecret: seti_1PaEoKGozbMWFnurhsTnE8O2_secret_QR72n7s1kxxxxxxxxxx
и я получаю эту ошибку Slim Application Error
Приложение не удалось запустить из-за следующей ошибки:
Код: Выделить всё
Details
Type: Stripe\Exception\InvalidRequestException
Message: This customer has no attached payment source or default payment method. Please consider adding a default payment method. For more information, visit https://stripe.com/docs/billing/subscriptions/payment-methods-setting#payment-method-priority.
File: public_html/api/vendor/stripe/stripe-php/lib/Exception/ApiErrorException.php
Line: 38
Trace
#0 public_html/api/vendor/stripe/stripe-php/lib/Exception/InvalidRequestException.php(35): Stripe\Exception\ApiErrorException::factory('This customer h...', 400, '{\n "error": {\n...', Array, Object(Stripe\Util\CaseInsensitiveArray), 'resource_missin...')
#1 /public_html/api/vendor/stripe/stripe-php/lib/ApiRequestor.php(189): Stripe\Exception\InvalidRequestException::factory('This customer h...', 400, '{\n "error": {\n...', Array, Object(Stripe\Util\CaseInsensitiveArray), 'resource_missin...', NULL)
#2 public_html/api/vendor/stripe/stripe-php/lib/ApiRequestor.php(151): Stripe\ApiRequestor::_specificAPIError('{\n "error": {\n...', 400, Object(Stripe\Util\CaseInsensitiveArray), Array, Array)
#3 public_html/api/vendor/stripe/stripe-php/lib/ApiRequestor.php(478): Stripe\ApiRequestor->handleErrorResponse('{\n "error": {\n...', 400, Object(Stripe\Util\CaseInsensitiveArray), Array)
#4 /public_html/api/vendor/stripe/stripe-php/lib/ApiRequestor.php(120): Stripe\ApiRequestor->_interpretResponse('{\n "error": {\n...', 400, Object(Stripe\Util\CaseInsensitiveArray))
#5 /public_html//api/vendor/stripe/stripe-php/lib/ApiOperations/Request.php(63): Stripe\ApiRequestor->request('post', '/v1/subscriptio...', Array, Array)
#6 public_htmlapi/vendor/stripe/stripe-php/lib/ApiOperations/Create.php(25): Stripe\ApiResource::_staticRequest('post', '/v1/subscriptio...', Array, NULL)
Подробнее здесь: https://stackoverflow.com/questions/787 ... stripe-php