簡體   English   中英

如何使用 Axios 向 API 發出 https 請求?

[英]How can I make a https request to Stripe API with Axios?

我正在嘗試將條帶集成到我的應用程序中,事實證明它確實具有挑戰性。

我的應用程序是 React 前端和 google Firebase 用於數據庫和托管。

經過幾天的文檔和反復試驗,我最終找到了這篇文章https://blog.risingstack.com/stripe-payments-integration-tutorial-javascript/

它非常全面且易於理解,因此我一直遵循這一點。 我的反應應用程序的結構是有一個 index.js 文件,它是 dom 的根,然后是一個 app.js 文件,它存儲到應用程序的 rest 的導航。

我正在嘗試添加能夠獲取客戶信用卡詳細信息並處理付款的商店頁面或結帳頁面。 所以我決定使用條紋。

最初,我嘗試使用谷歌 firebase 雲功能,但最終根本不起作用 - 旁注,我相信他們正在處理錯誤? - 然后我決定使用 express 和 axios 來處理 api 請求。

這似乎有效,除了來自條帶的響應是“服務器響應狀態為 405(不允許方法)”。

我認為這與我在本地運行它的事實有關,因此請求作為 http 請求發送,但我經驗不足,無法確定,在我將它部署到分期之前,我希望得到一些專家指導。 當我在這里時,如何將 Cors 原點更改為真實站點而不是本地主機?

代碼如下,在此先感謝。 羅里

// 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)

您不能從客戶端對 Stripe 進行服務器端 API 調用,並且您永遠不應該(永遠[永遠])將您的密鑰放在客戶端代碼中。

您需要使用某種服務器端代碼來完成該部分,或使用僅限客戶端的 Checkout

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM