集成七宝时无法读取属性 'create' of undefined error

Cannot read property 'create' of undefined error when integrating Shippo

我正在开发一个在后端使用 node.js 并在前端使用 react.js 的产品。在这个项目中,我试图整合七宝。他们为后端提供 api 信息,我已尝试 use/follow。我目前收到 cannot read 属性 'create' of undefined 错误,这是来自后端的 POST 500 Internal Server Error,但我不确定为什么会收到此错误以及我是否正在集成此系统正确。对于我可能做错的任何帮助或建议,我将不胜感激。谢谢!

后端:

Shippo.js

'use strict';

import express from 'express';
import shippo from 'shippo';
const shippoToken = process.env.SHIPPO_TOKEN || ''

const shippoRouter = express.Router();



shippoRouter.post(
    '/shippinginfo', 
function (req, res) {

var addressFrom  = {
    "name": "Jane Smith",
    "street1": "500 Riveride Dr",
    "city": "New York",
    "state": "NY",
    "zip": "10002",
    "country": "US"
};

const to = req.body
var addressTo = shippo.address.create({
    "name": to.fullName,
    "street1": to.address1,
    "street2": to.address2,
    "city": to.city,
    "state": to.state,
    "zip": to.postalCode,
    "country": to.country,
    "phone": to.phoneNumber,
    "email":to.email,
    "validate": true,
}, function(err, address) {
    // asynchronously called
});
    // asynchronously called

console.log(addressFrom)
console.log(addressTo)

var parcel = {
    "length": "5",
    "width": "5",
    "height": "5",
    "distance_unit": "in",
    "weight": "2",
    "mass_unit": "lb"
};

/*
shippo.shipment.create({
    "address_from": addressFrom,
    "address_to": addressTo,
    "parcels": [parcel],
    "async": false
}, function(err, shipment){
    // asynchronously called
});

shippo.shipment.rates('5e40ead7cffe4cc1ad45108696162e42');
//var rate = shipment.rates[0];

// Purchase the desired rate.
shippo.transaction.create({
    "rate": rate.object_id,
    "label_file_type": "PDF_4x6",
    "async": false
}, function(err, transaction) {
   // asynchronous callback
});*/

});

export default shippoRouter;

server.js

import express from 'express';
import cors from 'cors';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import path from 'path';
import shippoRouter from './shippo.js';

dotenv.config();

const app = express();
app.use(cors()); //and this
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost/AM', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
});

app.use('/api/shippo', shippoRouter);
app.get('/', (req, res) => {
    res.send('Server is ready');
});

app.use((err, req, res, next) => {
    res.status(500).send({ message: err.message });
});

const port = process.env.PORT || 5000;
app.listen(port, () => {
    console.log(`Serve at http://localhost:${port}`);
});

我如何尝试使用 axios 从我的前端获取运输信息 前端:

ShippingAddressScreen.js

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { saveShippingAddress } from '../actions/cartActions';
import CheckoutSteps from '../components/CheckoutSteps';
import { shippingInfo } from '../actions/shippingActions';

export default function ShippingAddressScreen(props) {
  const userSignin = useSelector((state) => state.userSignin);
  const { userInfo } = userSignin;
  const cart = useSelector((state) => state.cart);
  const { shippingAddress } = cart;
  if (!userInfo) {
    props.history.push('/signin');
  }
  const [fullName, setFullName] = useState(shippingAddress.fullName);
  const [address1, setAddress1] = useState(shippingAddress.address1);
  const [address2, setAddress2] = useState(shippingAddress.address2);
  const [city, setCity] = useState(shippingAddress.city);
  const [state, setState] = useState(shippingAddress.state);
  const [postalCode, setPostalCode] = useState(shippingAddress.postalCode);
  const [country, setCountry] = useState(shippingAddress.country);
  const [phoneNumber, setPhoneNumber] = useState('');
  const [email, setEmail] = useState('');
  const name = fullName;
  const street1 = address1;
  const street2 = address2;
  const zip = postalCode;
  const phone = phoneNumber;
  const dispatch = useDispatch();
  const submitHandler = (e) => {
    e.preventDefault();
    dispatch(
      saveShippingAddress({ fullName, address1, address2, city, state, postalCode, country })
    );
    props.history.push('/payment');
    dispatch(
      shippingInfo({ name, street1, street2, city, state, zip, country, phone, email })
    );
  };
  

 /* const shippingInfo = (e) => {
    e.preventDefault();
    
  };*/
  return (
    <div>
      <CheckoutSteps step1 step2></CheckoutSteps>
      <form className="form" onSubmit={submitHandler}>
        <div>
          <h1>Shipping Address</h1>
        </div>
        <div>
          <label htmlFor="fullName">Full Name</label>
          <input
            type="text"
            id="fullName"
            placeholder="Enter full name"
            value={fullName}
            onChange={(e) => setFullName(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="address1">Address</label>
          <input
            type="text"
            id="address1"
            placeholder="Enter address"
            value={address1}
            onChange={(e) => setAddress1(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="address2">Address</label>
          <input
            type="text"
            id="address2"
            placeholder="Enter address"
            value={address2}
            onChange={(e) => setAddress2(e.target.value)}
          ></input>
        </div>
        <div>
          <label htmlFor="city">City</label>
          <input
            type="text"
            id="city"
            name="city"
            placeholder="Enter city"
            value={city}
            onChange={(e) => setCity(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="state">State</label>
          <input
            type="text"
            id="state"
            placeholder="Enter state"
            value={state}
            onChange={(e) => setState(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="postalCode">Postal Code</label>
          <input
            type="text"
            id="postalCode"
            placeholder="Enter postal code"
            value={postalCode}
            onChange={(e) => setPostalCode(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="country">Country</label>
          <input
            type="text"
            id="country"
            placeholder="Enter country"
            value={country}
            onChange={(e) => setCountry(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="phoneNumber">Phone Number</label>
          <input
            type="text"
            id="phoneNumber"
            placeholder="Enter Phone Number"
            value={phoneNumber}
            onChange={(e) => setPhoneNumber(e.target.value)}
            required
          ></input>
        </div>
        <div>
          <label htmlFor="email">Email</label>
          <input
            type="text"
            id="email"
            placeholder="Enter Email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
          ></input>
        </div>
         <div>
           <button className="primary" type="submit">
            Continue
          </button>
        </div>
      </form>
    </div>
  );
}

ShippingActions.js

import Axios from 'axios';
import {
  SHIPPING_ADDRESS_FAIL,
  SHIPPING_ADDRESS_REQUEST,
  SHIPPING_ADDRESS_SUCCESS,
} from '../constants/shippingConstants';

export const shippingInfo = (name, street1, street2, city, state, zip, country, phone, email) => async (dispatch) => {
    dispatch({ type: SHIPPING_ADDRESS_REQUEST, payload: { name, email} });
    try {
      const { data } = await Axios.post('/api/shippo/shippinginfo', {
        name,
        street1,
        street2,
        city,
        state,
        zip,
        country,
        phone,
        email,
      });
      dispatch({ type: SHIPPING_ADDRESS_SUCCESS, payload: data });
    } catch (error) {
      dispatch({
        type: SHIPPING_ADDRESS_FAIL,
        payload:
          error.response && error.response.data.message
            ? error.response.data.message
            : error.message,
      });
    }
  };  

我还有一个 shippingReducer,shippingConstants,并在我的 store.js 中包含了减速器。

此外,如果这对您有帮助,https://goshippo.com/docs/reference/js#overview 是七宝的 Api 信息。

I am currently getting a cannot read property 'create' of undefined error

从您分享的代码来看,您似乎没有在 Shippo.js 中正确初始化 shippo 模块,因此 shippo.create 方法不存在。

在您的代码中,您正在导入 shippo 模块,但未使用密钥对其进行初始化:

import shippo from 'shippo';
const shippoToken = process.env.SHIPPO_TOKEN || ''

// <omitted>

var addressTo = shippo.address.create({
// <omitted>

请注意,shippoToken 在您的文件中仍未使用。

Shippo library documentation中,他们有下面的例子:

var shippo = require('shippo')('<YOUR_PRIVATE_KEY>');

因为你使用的是 ES 模块,你不能使用这个 one-liner,所以试试这样的东西:

import shippo from 'shippo';
const shippoToken = process.env.SHIPPO_TOKEN || ''

// initialize the shippo constructor with token:
const shippoClient = shippo(shippoToken);

// now you can use shippoClient instead of shippo:
var addressTo = shippoClient.address.create({
// <omitted>