如何解析 paymentMethod 对象?

How to parse paymentMethod Object?

我正在尝试列出我用户的所有付款方式。我主要是想获取品牌,到期日期和信用卡号的后4位数字。

我尝试了多种方法来解析从我的服务器发回的 JSON 支付方式对象,但我还没有成功。这是我在最近一次尝试中所做的。

在我的服务器中,我得到了所有用户付款方式的列表,并使用此功能将原始数据发送回我的客户端:

exports.listPaymentMethods = functions.https.onCall(async (data, context) => {
  const customerId = data.customer_id;
  const paymentMethods = await stripe.paymentMethods.list({
    customer: customerId,
    type: "card",
  });
  const pymtMethodData = paymentMethods.data;
  return {
    data: pymtMethodData,
  };
});

这是我从客户端调用函数的方式(它成功打印了原始数据):

func listPaymentMethods(customerID: String) {
    
    FirebaseReferenceManager.functions.httpsCallable("listPaymentMethods").call(["customer_id": customerID]) { (response, error) in
        
        if let error = error {
            print("failed to list customer's payment methods: \(error.localizedDescription)")
        }
        
        if let response = response?.data as? [String: Any] {
            let data = response["data"]
            print(data!) 
            self.parseJSON(data: data as! Data)
        }
        
    }
    
}

这是我用来存储支付方式数据的结构:

struct PaymentMethod: Decodable {
    let brand: String
    let expMonth: Int
    let expYear: Int
    let last4: Int
}

我尝试使用这个函数来解析数据,但是没有成功:

func parseJSON(data: Data) {
    let decoder = JSONDecoder()
    do {
        let decodedData = try decoder.decode(PaymentMethod.self, from: data)
        print(decodedData.brand)
        
    } catch {
        print(error)
    }
}

这是我从print(data!)

得到的原始数据
(
    {
    "billing_details" =         {
        address =             {
            city = "<null>";
            country = US;
            line1 = "<null>";
            line2 = "<null>";
            "postal_code" = 123456;
            state = "<null>";
        };
        email = "<null>";
        name = "<null>";
        phone = "<null>";
    };
    card =         {
        brand = visa;
        checks =             {
            "address_line1_check" = "<null>";
            "address_postal_code_check" = pass;
            "cvc_check" = pass;
        };
        country = US;
        "exp_month" = 12;
        "exp_year" = 2045;
        fingerprint = KKSbyUhUcKKSyto0;
        funding = credit;
        "generated_from" = "<null>";
        last4 = 4242;
        networks =             {
            available =                 (
                visa
            );
            preferred = "<null>";
        };
        "three_d_secure_usage" =             {
            supported = 1;
        };
        wallet = "<null>";
    };
    created = 1621941861;
    customer = "cus_JWaE2JEtbcI0JM";
    id = "pm_1IuyMzLVD5W50FFK2heBUTai";
    livemode = 0;
    metadata =         {
    };
    object = "payment_method";
    type = card;
}

)

我基本上是在尝试解析 JSON 数据,以便我可以拥有一个 PaymentMethod 数组(我在上面添加的结构),以便独立地引用来自该 PaymentMethod 的每个单独数据。

任何能引导我走向正确方向的东西都将不胜感激! :)

response.data已经被解析成Swift个对象,是一个[[String: Any]]。不再是Data,不需要JSONDecoder

PaymentMethod 添加自定义初始化:

init?(paymentDict: [String: Any]) {
    guard let card = paymentDict["card"] as? [String: Any] else { 
        print("There is no \"card\" key or it's not a [String: Any] in: \(paymentDict)")
        return nil
    }
    guard let brand = card["brand"] as? String else {
        print("There is no \"brand\" key or it's not a String in: \(card)")
        return nil
    }
    guard let expMonth = card["expMonth"] as? Int else {
        print("There is no \"expMonth\" key or it's not a Int in: \(card)")
        return nil
    }
    guard let expYear = card["expYear"] as? Int else {
        print("There is no \"expYear\" key or it's not a Int in: \(card)")
        return nil
    }
    guard let last4 = card["last4"] as? Int else {
        print("There is no \"last4\" key or it's not a Int in: \(card)")
        return nil
    }
    self.brand = brand
    self.expMonth = expMonth
    self.expYear = expYear
    self.last4 = last4
}

因为 response.dataDictionaryArray 而不是 Dictionary,如果您只对解析第一个感兴趣:

if let response = response?.data as? [String: Any] {
    if let data = response["data"] {
        if let firstPaymentDictionary = data.first {
            if let payment = PaymentMethod(paymentDict: firstPaymentDictionary) {
                print("Payment found: \(payment)")
            } else {
                print("Invalid payment)
            }
        } else {
            print("No payment found in `\(data)`")
        }
    } else {
        print("No data in \(response)")
    }
}

旁注:
我在 if let 中添加了所有 else 并在 guard letelse 中添加了显式打印,让您知道什么可能是错误的以及它们的含义。因为 if let/guard let 应该优于 !.