Как отправить полосовой ответ клиенту (Swift) с помощью облачной функции Firebase - PullRequest
0 голосов
/ 20 февраля 2019

Я создаю приложение для iOS, такое как Airbnb, используя Stripe и Firebase в качестве бэкэнда.Я следую за этим документом.https://medium.com/firebase-developers/go-serverless-manage-payments-in-your-apps-with-cloud-functions-for-firebase-3528cfad770.
Как сказано в документе, вот рабочий процесс, который я проделал (скажем, пользователь хочет что-то купить)
1.Пользователь отправляет информацию о платеже в базу данных Firebase в реальном времени, такую ​​как валюта суммы и токен карты)
2.Firebase запускает функцию, которая отправляет запрос на оплату (stripe.charge.create) в Stripe.
3.После получения ответа запишите его обратно в базу данных Firebase.если ответ не удался, напишите сообщение об ошибке в базу данных (см. функции userFacingMessage в index.js)
4.На стороне клиента (Swift) посмотрите базу данных Firebase, чтобы проверить ответ.
5. Если ответ успешный, отобразить успешное сообщение для пользователя.Если есть какие-либо ошибки, такие как (платеж не прошел из-за истечения срока действия кредитной карты), отобразите сообщение об ошибке пользователю (также отобразите сообщение «Пожалуйста, попробуйте еще раз»)

Я думаю, что это неправильный подход, потому что яЯ думаю, что пользователь должен знать ответ (если он был успешным или неудачным), как только Firebase получает ответ от Stripe. Другими словами, клиентская сторона (Swift) должна получить ответ сразу после получения ответа, прежде чем писать обратно в базу данных Firebase?знаете, как отправить ответ на стороне клиента?
Буду признателен за любую помощь

ChargeViewController.swift (на стороне клиента)

  func didTapPurchase(for amountCharge: String, for cardId: String) {
    print("coming from purchas button", amountCharge, cardId)

    guard let uid = Auth.auth().currentUser?.uid else {return}

    guard let cardId = defaultCardId else {return}
    let amount = amountCharge
    let currency = "usd"

    let value = ["source": cardId, "amount": amount, "currency": currency] as [String: Any]

    let ref = Database.database().reference().child("users").child(uid).child("charges")
    ref.childByAutoId().updateChildValues(value) { (err, ref) in
        if let err = err {
            print("failed to inserted charge into db", err)
        }

        print("successfully inserted charge into db")

       //Here, I want to get the response and display messages to user whether the response was successful or not.

    }

}

index.js (Облачные функции) Язык:node.js

exports.createStripeCharge = functions.database
.ref(‘users/{userId}/charges/{id}’)
.onCreate(async (snap, context) => {
const val = snap.data();
try {
// Look up the Stripe customer id written in createStripeCustomer
const snapshot = await admin.database()
.ref(`users/stripe/${context.params.userId}/stripe_customer_id`)
.once('value');

const snapval = snapshot.data();
const customer = snapval.stripe_customer_id;
// Create a charge using the pushId as the idempotency key
// protecting against double charges
const amount = val.amount;
const idempotencyKey = context.params.id;
const charge = {amount, currency, customer};
if (val.source !== null) {
   charge.source = val.source;
}
const response = await stripe.charges
    .create(charge, {idempotency_key: idempotencyKey});
// If the result is successful, write it back to the database
//*I want to send this response to the client side but not sure how if I can do it nor not*
return snap.ref.set(response);
} catch(error) {
    await snap.ref.set(error: userFacingMessage(error));
}
});
    // Sanitize the error message for the user
function userFacingMessage(error) {
  return error.type ? error.message : 'An error occurred, developers have been alerted';
}

1 Ответ

0 голосов
/ 26 февраля 2019

Исходя из поста Фрэнкса здесь , я решил подождать изменения в базе данных Firebase.Ниже приведен рабочий процесс и код (в файле index.js нет изменений):

1. Пользователь отправляет информацию о платеже в базу данных Firebase в реальном времени (например, сумму валюты и токен карты) по пути / users / {userId} / charge
2. Firebase запускает функцию, которая отправляет запрос на оплату (stripe.charge.create) в Stripe.
3. После получения ответа запишите его обратно в базу данных Firebase.если ответ не удался, напишите сообщение об ошибке в базу данных (см. функции userFacingMessage в index.js)
4. На стороне клиента (Swift) дождитесь изменения в базе данных Firebase, чтобы проверить, был ли ответ успешным или нетс помощью Observe (.childChanged) (см. код Swift)
5. Если ответ успешен, отобразить успешное сообщение для пользователя.Если есть какие-либо ошибки, такие как (платеж не прошел из-за истечения срока действия кредитной карты), отобразите сообщение об ошибке пользователю (также отобразите сообщение «Пожалуйста, попробуйте еще раз»)

ChargeViewController.swift

func didTapPurchase(for amountCharge: String, for cardId: String) {
print("coming from purchas button", amountCharge, cardId)

guard let uid = Auth.auth().currentUser?.uid else {return}

guard let cardId = defaultCardId else {return}
let amount = amountCharge
let currency = "usd"

let value = ["source": cardId, "amount": amount, "currency": currency] as [String: Any]

let ref = Database.database().reference().child("users").child(uid).child("charges")
ref.childByAutoId().updateChildValues(value) { (err, ref) in
    if let err = err {
        print("failed to inserted charge into db", err)
    }

    print("successfully inserted charge into db")

   //Here, Wait for the response that has been changed
   waitForResponseBackFromStripe(uid: uid)

  }

 }

func waitForResponseBackFromStripe(uid: String) {

    let ref = Database.database().reference().child("users").child(uid).child("charges")
    ref.observe(.childChanged, with: { (snapshot) in

        guard let dictionary = snapshot.value as? [String: Any] else {return}

        if let errorMessage = dictionary["error"] {
            print("there's an error happening so display error message")
            let alertController = UIAlertController(title: "Sorry:(\n \(errorMessage)", message: "Please try again", preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
            //alertController.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
            self.present(alertController, animated: true, completion: nil)
            return

        } else {
            let alertController = UIAlertController(title: "Success!", message: "The charge was Successful", preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
            self.present(alertController, animated: true, completion: nil)
        }
    }) { (err) in
        print("failed to fetch charge data", err.localizedDescription)
        return
    }
}

Если я сделал что-то логически неправильное, пожалуйста, дайте мне знать, но это пока работает для меня
Надеюсь, это поможет кому-то, кто интегрирует платежи Firebase и Stripe

...