spaps 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/local-server.js +172 -12
package/package.json
CHANGED
package/src/local-server.js
CHANGED
|
@@ -37,7 +37,7 @@ class LocalServer {
|
|
|
37
37
|
origin: true,
|
|
38
38
|
credentials: true,
|
|
39
39
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
40
|
-
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key', 'X-Test-User', 'x-local-mode'],
|
|
40
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key', 'X-Test-User', 'x-local-mode', 'X-Local-Mode'],
|
|
41
41
|
}));
|
|
42
42
|
|
|
43
43
|
// Body parsing
|
|
@@ -608,10 +608,10 @@ class LocalServer {
|
|
|
608
608
|
}
|
|
609
609
|
});
|
|
610
610
|
|
|
611
|
-
// POST /api/stripe/products - Create new product
|
|
611
|
+
// POST /api/stripe/products - Create new product with optional price
|
|
612
612
|
this.app.post('/api/stripe/products', async (req, res) => {
|
|
613
613
|
try {
|
|
614
|
-
const { name, description, images, metadata = {}, active = true } = req.body;
|
|
614
|
+
const { name, description, images, metadata = {}, active = true, price, currency = 'usd' } = req.body;
|
|
615
615
|
|
|
616
616
|
if (!name) {
|
|
617
617
|
return res.status(400).json({
|
|
@@ -634,29 +634,67 @@ class LocalServer {
|
|
|
634
634
|
}
|
|
635
635
|
});
|
|
636
636
|
|
|
637
|
+
let stripePrice = null;
|
|
638
|
+
|
|
639
|
+
// If price is provided, create a price for the product
|
|
640
|
+
if (price !== undefined && price !== null && price !== '') {
|
|
641
|
+
stripePrice = await stripe.prices.create({
|
|
642
|
+
product: stripeProduct.id,
|
|
643
|
+
unit_amount: parseInt(price), // Price in cents
|
|
644
|
+
currency: currency,
|
|
645
|
+
metadata: {
|
|
646
|
+
spaps_managed: 'true',
|
|
647
|
+
created_by: 'spaps_cli'
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// Update product with default price
|
|
652
|
+
await stripe.products.update(stripeProduct.id, {
|
|
653
|
+
default_price: stripePrice.id
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Fetch the updated product with default_price
|
|
658
|
+
const updatedProduct = await stripe.products.retrieve(stripeProduct.id, {
|
|
659
|
+
expand: ['default_price']
|
|
660
|
+
});
|
|
661
|
+
|
|
637
662
|
res.json({
|
|
638
663
|
success: true,
|
|
639
664
|
data: {
|
|
640
665
|
product: {
|
|
641
|
-
id:
|
|
642
|
-
name:
|
|
643
|
-
description:
|
|
644
|
-
images:
|
|
645
|
-
active:
|
|
646
|
-
metadata:
|
|
647
|
-
created:
|
|
666
|
+
id: updatedProduct.id,
|
|
667
|
+
name: updatedProduct.name,
|
|
668
|
+
description: updatedProduct.description,
|
|
669
|
+
images: updatedProduct.images,
|
|
670
|
+
active: updatedProduct.active,
|
|
671
|
+
metadata: updatedProduct.metadata,
|
|
672
|
+
created: updatedProduct.created,
|
|
673
|
+
default_price: updatedProduct.default_price ? {
|
|
674
|
+
id: updatedProduct.default_price.id,
|
|
675
|
+
unit_amount: updatedProduct.default_price.unit_amount,
|
|
676
|
+
currency: updatedProduct.default_price.currency
|
|
677
|
+
} : null
|
|
648
678
|
}
|
|
649
679
|
}
|
|
650
680
|
});
|
|
651
681
|
} else {
|
|
652
682
|
// Create locally
|
|
683
|
+
const productPrice = price ? parseInt(price) : 0;
|
|
653
684
|
const product = this.adminManager.createProduct({
|
|
654
685
|
name,
|
|
655
686
|
description,
|
|
656
|
-
price:
|
|
657
|
-
currency:
|
|
687
|
+
price: productPrice,
|
|
688
|
+
currency: currency
|
|
658
689
|
});
|
|
659
690
|
|
|
691
|
+
// Add mock default_price structure for consistency
|
|
692
|
+
product.default_price = productPrice > 0 ? {
|
|
693
|
+
id: `price_${product.id}`,
|
|
694
|
+
unit_amount: productPrice,
|
|
695
|
+
currency: currency
|
|
696
|
+
} : null;
|
|
697
|
+
|
|
660
698
|
res.json({
|
|
661
699
|
success: true,
|
|
662
700
|
data: { product }
|
|
@@ -730,6 +768,128 @@ class LocalServer {
|
|
|
730
768
|
}
|
|
731
769
|
});
|
|
732
770
|
|
|
771
|
+
// POST /api/stripe/prices - Create a new price for a product
|
|
772
|
+
this.app.post('/api/stripe/prices', async (req, res) => {
|
|
773
|
+
try {
|
|
774
|
+
const { product_id, unit_amount, currency = 'usd', recurring, metadata = {} } = req.body;
|
|
775
|
+
|
|
776
|
+
if (!product_id || !unit_amount) {
|
|
777
|
+
return res.status(400).json({
|
|
778
|
+
success: false,
|
|
779
|
+
error: { message: 'Product ID and unit amount are required' }
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (USE_REAL_STRIPE) {
|
|
784
|
+
const priceData = {
|
|
785
|
+
product: product_id,
|
|
786
|
+
unit_amount: parseInt(unit_amount),
|
|
787
|
+
currency,
|
|
788
|
+
metadata: {
|
|
789
|
+
...metadata,
|
|
790
|
+
spaps_managed: 'true'
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
// Add recurring if specified
|
|
795
|
+
if (recurring) {
|
|
796
|
+
priceData.recurring = recurring;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const stripePrice = await stripe.prices.create(priceData);
|
|
800
|
+
|
|
801
|
+
res.json({
|
|
802
|
+
success: true,
|
|
803
|
+
data: {
|
|
804
|
+
price: {
|
|
805
|
+
id: stripePrice.id,
|
|
806
|
+
product: stripePrice.product,
|
|
807
|
+
unit_amount: stripePrice.unit_amount,
|
|
808
|
+
currency: stripePrice.currency,
|
|
809
|
+
recurring: stripePrice.recurring,
|
|
810
|
+
metadata: stripePrice.metadata
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
} else {
|
|
815
|
+
// Mock price creation
|
|
816
|
+
const price = {
|
|
817
|
+
id: `price_${Date.now()}`,
|
|
818
|
+
product: product_id,
|
|
819
|
+
unit_amount: parseInt(unit_amount),
|
|
820
|
+
currency,
|
|
821
|
+
recurring,
|
|
822
|
+
metadata
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
res.json({
|
|
826
|
+
success: true,
|
|
827
|
+
data: { price }
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
} catch (error) {
|
|
831
|
+
console.error('Create price error:', error);
|
|
832
|
+
res.status(500).json({
|
|
833
|
+
success: false,
|
|
834
|
+
error: {
|
|
835
|
+
code: 'CREATE_PRICE_ERROR',
|
|
836
|
+
message: error.message || 'Failed to create price'
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
// PUT /api/stripe/products/:productId/default-price - Update product's default price
|
|
843
|
+
this.app.put('/api/stripe/products/:productId/default-price', async (req, res) => {
|
|
844
|
+
try {
|
|
845
|
+
const { productId } = req.params;
|
|
846
|
+
const { price_id } = req.body;
|
|
847
|
+
|
|
848
|
+
if (!price_id) {
|
|
849
|
+
return res.status(400).json({
|
|
850
|
+
success: false,
|
|
851
|
+
error: { message: 'Price ID is required' }
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
if (USE_REAL_STRIPE) {
|
|
856
|
+
const stripeProduct = await stripe.products.update(productId, {
|
|
857
|
+
default_price: price_id
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
res.json({
|
|
861
|
+
success: true,
|
|
862
|
+
data: {
|
|
863
|
+
product: {
|
|
864
|
+
id: stripeProduct.id,
|
|
865
|
+
name: stripeProduct.name,
|
|
866
|
+
default_price: stripeProduct.default_price
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
} else {
|
|
871
|
+
res.json({
|
|
872
|
+
success: true,
|
|
873
|
+
data: {
|
|
874
|
+
product: {
|
|
875
|
+
id: productId,
|
|
876
|
+
default_price: price_id
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
} catch (error) {
|
|
882
|
+
console.error('Update default price error:', error);
|
|
883
|
+
res.status(500).json({
|
|
884
|
+
success: false,
|
|
885
|
+
error: {
|
|
886
|
+
code: 'UPDATE_DEFAULT_PRICE_ERROR',
|
|
887
|
+
message: error.message || 'Failed to update default price'
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
|
|
733
893
|
// DELETE /api/stripe/products/:productId - Archive product
|
|
734
894
|
this.app.delete('/api/stripe/products/:productId', async (req, res) => {
|
|
735
895
|
try {
|