Javascript 我如何向Axios发送https请求以剥离API?

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文件,用于存储应用程序其余部分的导航 我正在尝试添加一个商店页面或结帐页面,可以获取客户的信用卡详细信息并处理付款。所以我决定用条

我正在尝试将stripe集成到我的应用程序中,事实证明这是一项非常具有挑战性的工作

我的应用程序是React前端和googlefirebase,用于数据库和托管

经过几天对文档、线索和错误的反复阅读,我终于找到了这篇文章

这是相当全面和可以理解的,所以我一直遵循这一点。 我的react应用程序的结构是这样的:一个index.js文件是dom的根,然后是一个app.js文件,用于存储应用程序其余部分的导航

我正在尝试添加一个商店页面或结帐页面,可以获取客户的信用卡详细信息并处理付款。所以我决定用条纹

最初,我尝试使用google firebase云功能,但最终完全无法工作。请注意,我相信它们正在处理一个bug然后我决定使用express和axios来处理api请求

除了stripe的响应是“服务器响应状态为405(不允许使用方法)”之外,这似乎是可行的

我认为这与我在本地运行这个程序有关,因此请求将作为http请求发送,但我太缺乏经验,无法确定,在将其部署到登台之前,我希望得到一些专家的指导。当我这样做的时候,如何将Cors源代码更改为真实的站点而不是本地主机

代码如下,提前谢谢。 罗里

//文件位置//
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)