我正在浏览文档,但我看不出哪里出了问题。有人能透露一些信息吗?我认为我没有正确引用函数((或firebase。谢谢以下是所有代码:
firebase.js
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import 'firebase/functions'
const dev = true
export const app = !firebase.apps.length ? firebase.initializeApp({
apiKey: "AIzaSyBDrj-rL-Mzswu9VXhgp-RuvP9Hvl1kqQ0",
authDomain: "edit-elements.firebaseapp.com",
databaseURL: "https://edit-elements-default-rtdb.firebaseio.com",
projectId: "edit-elements",
storageBucket: "edit-elements.appspot.com",
messagingSenderId: "340652433701",
appId: "1:340652433701:web:a26472592c1538bbac7acc",
measurementId: "G-945XC7348K"
}) : firebase.app()
export const auth = app.auth()
export const db = app.firestore()
export const functions = dev ? app.functions().useEmulator("localhost", '5001') : app.functions()
checkout.js(其中调用函数createFreeOrder(
import PayPalComponent from '../components/PayPalComponent'
import { Button, Grid, TextField, Typography } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import { useAuth } from '../contexts/AuthContext'
import { useCart } from '../contexts/CartContext'
import Cart from '../components/Cart'
import LoginForm from '../components/LoginForm'
import SignupForm from '../components/SignupForm'
import { useEffect, useState } from 'react'
import { client } from '../prismic-configuration'
import { Actions } from '../utils/cartActions'
import { db, functions } from '../firebase'
const theme = makeStyles({
checkoutContainer: {
margin: 'auto',
maxWidth: '1200px',
paddingTop: '2rem',
'&: section': {
minHeight: '100vh'
},
couponInput: {
'& fieldset': {
borderRadius: '6px 0px 0px 6px'
}
}
}
})
export default function Checkout() {
const { currentUser } = useAuth()
const { cart, cartTotal, dispatch } = useCart()
const styles = theme()
const [showLogin, setShowLogin] = useState(false)
const hasItems = Boolean(Object.keys(cart.products).length)
const [couponCode, setCouponCode] = useState('')
const [couponError, setCouponError] = useState('')
const cartCost = cartTotal()
console.log(functions, db)
const checkCoupon = async () => {
setCouponError('')
if (couponCode == '') return null
console.log('NOTICE: Please note that the coupons are checked server-side, so any attempt to manipulate them here will do nothing, and you *will* be charged the price without a valid coupon')
await client.getByUID('coupon', couponCode.toLowerCase())
.then(res => {
if (res.data) dispatch({ type: Actions.ADD_COUPON, payload: res })
})
.catch(err => setCouponError('No Coupon / Expired Coupon'))
}
const handleFreeOrder = async () => {
const createFreeOrder = functions.httpsCallable('createFreeOrder')
createFreeOrder(cart.products)
}
return (
<Grid container direction="column" className={styles.checkoutContainer}>
<Grid item>
<Typography variant="h1" mb={'2rem'}>Shopping Cart</Typography>
</Grid>
{ !currentUser &&
<>
<Grid item p={'.5rem'}>
<Typography variant="subtitle1">Please note that accounts are required for purchase, as it allows us to securely generate download tokens and process invoices.</Typography>
</Grid>
{ !showLogin ?
<Grid item>
<SignupForm dontRedirect/>
<Typography>Already have an account? <span style={{cursor: 'pointer'}} onClick={prev => setShowLogin(true)}>Click here</span> to login.</Typography>
</Grid>
:
<Grid item>
<LoginForm />
<Typography>Don't have an account? <span style={{color: '#5e5e5e', cursor: 'pointer'}} onClick={prev => setShowLogin(false)}>Click here</span> to login.</Typography>
</Grid>
}
</>
}
<Grid container>
<Grid item xs={12}>
<Cart />
</Grid>
{ hasItems &&
<Grid item xs={12} sx={{textAlign: 'right'}} p={3} >
<TextField className={styles.couponInput} helperText={couponError} label="Coupon Code" value={couponCode.toUpperCase()} onChange={(e) => setCouponCode(e.target.value)} /><Button disableElevation sx={{padding: '1rem', borderRadius: '0px 6px 6px 0px'}} onClick={ checkCoupon } variant="contained">Check Code</Button>
</Grid>
}
{ hasItems &&
<Grid container style={{textAlign: 'right'}} justifyContent="flex-end">
<Grid item xs={12} sm={8} p={3}>
{ (cartTotal() > 0.00) ? <PayPalComponent /> : <Button onClick={handleFreeOrder} color="amber" style={{ padding: '1rem' }} variant="contained">Claim Product(s)</Button>}
</Grid>
</Grid>
}
</Grid>
</Grid>
)
}
functions/index.js文件(firebase函数文件(:
const firebase = require('firebase-admin');
const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// functions.logger.info("Hello logs!", {structuredData: true});
// response.send("Hello from Firebase!");
// });
exports.newsletterSignup = functions.https.onCall((data, ctx) => {
console.log('ctx obj', ctx, 'ctx req', ctx.req)
const sgMail = require('@sendgrid/mail')
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
const msg = ("hello")
res.send('Received').end()
})
exports.createFreeOrder = functions.https.onCall(async (data, ctx) => {
const firebase = require('firebase-admin')
const db = require('firebase/firebase-firestore')
console.log('data and ctx', data, ctx)
})
exports.createPaypalOrder = functions.https.onCall(async (data, ctx) => {
const checkoutNodeSDK = require('@paypal/checkout-server-sdk')
const Prismic = require('@prismicio/client')
const products = data.products
const env = () => {
const clientId = process.env.PAYPAL_CLIENT.id
const clientSecret = process.env.PAYPAL_CLIENT.clientSecret
return new checkoutNodeSDK.core.SandboxEnvironment(clientId, clientSecret)
}
const client = () => {
return new checkoutNodeSDK.core.PayPalHttpClient(env)
}
// The request for PayPal
const request = new paypal.orders.OrdersCreateRequest()
request.prefer('return=representation')
request.requestBody({
intent: 'Capture',
purchase_units: [{
amount: {
currency_code: 'USD',
value: 0
}
}]
})
let order
try {
order = await client().execute(request)
} catch {
}
})
问题就在这里:
export const functions = dev ? app.functions().useEmulator("localhost", '5001') : app.functions()
useEmulator
方法上不存在httpsCallable
。相反,在尝试使用模拟器之前,您应该指定使用模拟器,如下所示:
const dev = true;
const functions = app.functions();
// Checking if dev is true. If yes, use emulator
if (dev) functions.useEmulator("localhost", 5001)
export {functions}