Javascript 我如何向Axios发送https请求以剥离API?
我正在尝试将stripe集成到我的应用程序中,事实证明这是一项非常具有挑战性的工作 我的应用程序是React前端和googlefirebase,用于数据库和托管 经过几天对文档、线索和错误的反复阅读,我终于找到了这篇文章 这是相当全面和可以理解的,所以我一直遵循这一点。 我的react应用程序的结构是这样的:一个index.js文件是dom的根,然后是一个app.js文件,用于存储应用程序其余部分的导航 我正在尝试添加一个商店页面或结帐页面,可以获取客户的信用卡详细信息并处理付款。所以我决定用条纹 最初,我尝试使用google firebase云功能,但最终完全无法工作。请注意,我相信它们正在处理一个bug然后我决定使用express和axios来处理api请求 除了stripe的响应是“服务器响应状态为405(不允许使用方法)”之外,这似乎是可行的 我认为这与我在本地运行这个程序有关,因此请求将作为http请求发送,但我太缺乏经验,无法确定,在将其部署到登台之前,我希望得到一些专家的指导。当我这样做的时候,如何将Cors源代码更改为真实的站点而不是本地主机 代码如下,提前谢谢。 罗里Javascript 我如何向Axios发送https请求以剥离API?,javascript,node.js,reactjs,stripe-payments,integration,Javascript,Node.js,Reactjs,Stripe Payments,Integration,我正在尝试将stripe集成到我的应用程序中,事实证明这是一项非常具有挑战性的工作 我的应用程序是React前端和googlefirebase,用于数据库和托管 经过几天对文档、线索和错误的反复阅读,我终于找到了这篇文章 这是相当全面和可以理解的,所以我一直遵循这一点。 我的react应用程序的结构是这样的:一个index.js文件是dom的根,然后是一个app.js文件,用于存储应用程序其余部分的导航 我正在尝试添加一个商店页面或结帐页面,可以获取客户的信用卡详细信息并处理付款。所以我决定用条
//文件位置//
Olas/Server/index.js
//文件位置//
const express=require('express');
常量头盔=需要(“头盔”);
const cors=需要(“cors”);
常量app=express();
常数端口=3001;
const stripe=require('stripe')('****秘密测试密钥****');
应用程序使用(cors)({
来源:[/https:\/\/localhost:\d+$/],
AllowedHeader:['Content-Type','Authorization'],
凭据:正确
}));
app.post('/api/shop/order',异步(req,res)=>{
const order=req.body.order;
const source=req.body.source;
试一试{
const stripeOrder=wait stripe.orders.create(order);
log('Order completed:${stripeOrder.id}');
等待stripe.orders.pay(stripeOrder.id,{source})
}捕捉(错误){
//在此处处理条带错误:没有此类优惠券、sku等
log(`Order error:${err}`);
返回res.sendStatus(404);
}
返回res.sendStatus(200);
});
app.get('/api/',(req,res)=>res.send({version:'1.0'}));
app.listen(端口,()=>console.log(`Example app listening on port${port}!`));
//文件位置//
src/Pages/Shop.js
//文件位置//
从“React”导入React,{Component};
从“react stripe elements”导入{CardElement};
从“道具类型”导入道具类型;
从“axios”导入axios;
从“查询字符串对象”导入qs;
从“react stripe elements”导入{injectStripe}
常数价格={
香蕉:150,
黄瓜:100
};
常数乘积={
香蕉:“prod_HQJX0o5TAu8pJi”,
黄瓜:“prod_hqjyalb1nsbj”,
};
常量stripeAuthHeader={
“内容类型”:“应用程序/x-www-form-urlencoded”,
‘授权’:‘承载人***测试密钥`};
类。组件{
建造师(道具){
超级(道具);
此.state={
取景:假,
购物车:{
香蕉:0,
黄瓜:0
},
优惠券:“”,
电子邮件:“”,
名称:“”,
地址:{
第1行:“”,
城市:'',
声明:'',
国家:“,
邮政编码:''
},
};
this.handleCartChange=this.handleCartChange.bind(this);
this.handleCartReset=this.handleCartReset.bind(this);
this.handleAddressChange=this.handleAddressChange.bind(this);
this.handleChange=this.handleChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
}
手把手更换(evt){
evt.preventDefault()
const cart=this.state.cart
购物车[evt.target.name]+=parseInt(evt.target.value)
this.setState({cart})
}
handleCartReset(evt){
evt.preventDefault()
this.setState({cart:{banana:0,cumber:0})
}
手动更换(evt){
evt.preventDefault()
常量地址=this.state.address
地址[evt.target.name]=evt.target.value
this.setState({address})
}
手柄更换(evt){
evt.preventDefault()
this.setState({[evt.target.name]:evt.target.value})
}
handleSubmit(evt){
evt.preventDefault();
this.setState({fetching:true});
const cart=this.state.cart;
this.props.stripe.createToken()。然后({token})=>{
//创建订单
常量命令={
货币:美元,
项目:Object.keys(购物车).filter((名称)=>cart[name]>0?true:false).map(
名称=>{
返回{
输入:“好”,
父项:产品[名称],
数量:购物车[名称]
}
}),
电子邮件:this.state.email,
装运:{
名称:this.state.name,
地址:this.state.address
}
}
//添加优惠券(如有)
if(本州优惠券){
order.coupon=this.state.coupon
}
console.log(令牌);
//这是前面示例中的简单直接充电//
//const price=cart.banana*prices.banana+cart.cumber*prices.cumber
//axios.post('https://api.stripe.com/v1/charges',
//严格化({
//来源:token.id,
//金额:价格,
//货币:美元
// }),
//{headers:stripeAuthHeader})
//。然后((resp)=>{
//this.setState({fetching:false});
//提醒('谢谢您的购买!您的卡已被收取:${(resp.data.amount/100)。ToLocalString(\'en-US\',{style:\'currency\',currency:\'usd\'})}`)
// })
//.catch(错误=>{
//this.setState({fetching:false});
//控制台.log(错误)
// })
//.catch(错误=>{
//this.setState({fetching:false});
//console.log(错误)
// })
// File Location //
Olas/Server/index.js
// File Location //
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const app = express();
const port = 3001;
const stripe = require('stripe')('****SECRET TEST KEY****');
app.use(cors({
origin: [/https:\/\/localhost:\d+$/],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
app.post('/api/shop/order', async(req, res) => {
const order = req.body.order;
const source = req.body.source;
try {
const stripeOrder = await stripe.orders.create(order);
console.log('Order completed: ${stripeOrder.id}');
await stripe.orders.pay(stripeOrder.id, {source})
} catch (err) {
// Handle stripe errors here: No such coupon, sku, ect
console.log(`Order error: ${err}`);
return res.sendStatus(404);
}
return res.sendStatus(200);
});
app.get('/api/', (req, res) => res.send({ version: '1.0' }));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
// File Location //
src/Pages/Shop.js
// File Location //
import React, {Component} from "react";
import { CardElement } from 'react-stripe-elements';
import PropTypes from 'prop-types';
import axios from 'axios';
import qs from 'query-string-object';
import { injectStripe } from 'react-stripe-elements'
const prices = {
banana: 150,
cucumber: 100
};
const products = {
banana: "prod_HQJX0o5TAu8pJi",
cucumber: "prod_HQJYaYAlB1nSbJ",
};
const stripeAuthHeader = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer *** TEST KEY`};
class Shop extends React.Component {
constructor(props) {
super(props);
this.state = {
fetching: false,
cart: {
banana: 0,
cucumber: 0
},
coupon: '',
email: '',
name: '',
address : {
line1: '',
city: '',
state: '',
country: '',
postal_code: ''
},
};
this.handleCartChange = this.handleCartChange.bind(this);
this.handleCartReset = this.handleCartReset.bind(this);
this.handleAddressChange = this.handleAddressChange.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleCartChange(evt) {
evt.preventDefault()
const cart = this.state.cart
cart[evt.target.name]+= parseInt(evt.target.value)
this.setState({cart})
}
handleCartReset(evt) {
evt.preventDefault()
this.setState({cart:{banana: 0, cucumber: 0}})
}
handleAddressChange(evt) {
evt.preventDefault()
const address = this.state.address
address[evt.target.name] = evt.target.value
this.setState({address})
}
handleChange(evt) {
evt.preventDefault()
this.setState({[evt.target.name]: evt.target.value})
}
handleSubmit(evt) {
evt.preventDefault();
this.setState({fetching:true});
const cart = this.state.cart;
this.props.stripe.createToken().then(({token}) => {
//Create Order
const order ={
currency: 'usd',
items: Object.keys(cart).filter((name) => cart[name] >0 ? true: false).map(
name => {
return {
type: 'good',
parent: products[name],
quantity: cart[name]
}
}),
email: this.state.email,
shipping: {
name: this.state.name,
address: this.state.address
}
}
// Add coupon if given
if (this.state.coupon) {
order.coupon = this.state.coupon
}
console.log(token);
//This is a simple direct charge from an earlier example//
// const price = cart.banana * prices.banana + cart.cucumber * prices.cucumber
// axios.post('https.//api.stripe.com/v1/charges',
// qs.stringify({
// source: token.id,
// amount: price,
// currency: 'usd'
// }),
// {headers:stripeAuthHeader})
// .then((resp) => {
// this.setState({fetching:false});
// alert('Thank you for your purchase! Your card has been charged with: ${(resp.data.amount / 100).toLocaleString(\'en-US\', {style: \'currency\', currency: \'usd\'})}`')
// })
// .catch(error => {
// this.setState({fetching: false});
// console.log(error)
// })
// .catch(error=> {
// this.setState({fetching:false});
// console.log(error)
// })
axios.post('http:localhost:3001/api/shop/order', {order, source: token.id})
.then(() => {
this.setState({fetching: false})
alert(`Thank you for your purchase!`)
})
.catch(error => {
this.setState({fetching: false})
console.log(error);
})
})
.catch(error => {
this.setState({fetching: false})
console.log(error)
})
}
render() {
const state = this.state;
const fetching = this.state.fetching;
const cart = this.state.cart;
const address = this.state.address;
const submittable = (cart.banana !== 0 || cart.cucumber !== 0) && state.email && state.name && address.line1 && address.city && address.state && address.country && address.postal_code
return (
<form onSubmit={this.handleSubmit} style={{width: '550px', margin: '20px', padding: '10px', border: '2px solid lightseagreen', borderRadius: '10px'}}>
<div>
Banana {(prices.banana / 100).toLocaleString('en-US', {style: 'currency', currency: 'usd'})}:
<div>
<button name={"banana"} value={1} onClick={this.handleCartChange}>+</button>
<button name={"banana"} value={-1} onClick={this.handleCartChange} disabled={cart.banana <=0}>-</button>
{cart.banana}
</div>
</div>
<div>
Cucumber {(prices.cucumber / 100).toLocaleString('en-US', {style:'currency', currency:'usd'})}:
<div>
<button name={"cucumber"} value={1} onClick={this.handleCartChange}>+</button>
<button name={"cucumber"} value={-1} onClick={this.handleCartChange} disabled={cart.cucumber <=0}>-</button>
{cart.cucumber}
</div>
</div>
<button onClick={this.handleCartReset}>Reset Cart</button>
<div style={{width: '450px', margin: '10px', padding: '5px', border: '2px solid green', borderRadius: '10px'}}>
<CardElement style={{base: {fontSize: '18px'}}}/>
</div>
<div>Name: <input type="text" name="name" onChange={this.handleChange}/></div>
<div>Email: <input type="text" name="email" onChange={this.handleChange}/></div>
<div>Address Line: <input type="text" name="line1" onChange={this.handleAddressChange}/></div>
<div>City: <input type="text" name="city" onChange={this.handleAddressChange}/></div>
<div>State: <input type="text" name="state" onChange={this.handleAddressChange}/></div>
<div>Country: <input type="text" name="country" onChange={this.handleAddressChange}/></div>
<div>Postal Code: <input type="text" name="postal_code" onChange={this.handleAddressChange}/></div>
<div>Coupon Code: <input type="text" name="coupon" onChange={this.handleChange}/></div>
{!fetching ?
<button type={'submit'} disabled={cart.banana=== 0 && cart.cucumber===0}>Purchase</button>
: 'Purchasing...'
}
Price: {((cart.banana * prices.banana + cart.cucumber * prices.cucumber) / 100).toLocaleString('en-US', {style: 'currency', currency: 'usd'})}
</form>
);
}
}
Shop.propTypes = {
stripe: PropTypes.shape({
createToken: PropTypes.func.isRequired}).isRequired
};
export default injectStripe(Shop)