iosswiftstripe-paymentsapplepaypasskit

how can I create a token for Apple Pay with Stripe


So my ultimate goal is to be able to just make test payments with Apple Pay on Stripe, whether that be with a token or something else.

**EDIT **I have this function I use to gather card info from the stored card in the Wallet:

 func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
    guard let paymentIntentClientSecret = paymentIntentClientSecret else {
        return;
    }

    let backendUrlForToken = "https://us-central1-xxxxxx-41f12.cloudfunctions.net/createStripeToken"
    let url = URL(string: backendUrlForToken)
    let pkToken = String(data: paymentInformation.token.paymentData, encoding: .utf8)
    guard let name = paymentInformation.billingContact?.name else { return }
    let nameFormatter = PersonNameComponentsFormatter()
    nameFormatter.string(from: name)
    let json: [String: Any] = [
        "card": [
            
            "address_city": paymentInformation.billingContact?.postalAddress?.city,
            "address_country": paymentInformation.billingContact?.postalAddress?.country,
            "address_line1": paymentInformation.billingContact?.postalAddress?.street,
            "address_state": paymentInformation.billingContact?.postalAddress?.state,
            "address_zip": paymentInformation.billingContact?.postalAddress?.postalCode,
            "name": name
        ],
        "muid": UIDevice.current.identifierForVendor?.uuidString,
        "pk_token": pkToken,
        "pk_token_instrument_name": paymentInformation.token.paymentMethod.displayName,
        "pk_token_payment_network": paymentInformation.token.paymentMethod.network?.rawValue,
        "pk_token_transaction_id": paymentInformation.token.transactionIdentifier
    ]
    var request = URLRequest(url: url!)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try? JSONSerialization.data(withJSONObject: json)
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        guard let response = response as? HTTPURLResponse,
              response.statusCode == 200,
              let data = data,
              let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
              let token = json["id"] as? String else {
                print("Error getting Stripe token")
                return
            }
        print("\(token)")
        self.stripeToken = token
        
    }
    
    task.resume()
    
    
    let error = NSError()
    completion(paymentIntentClientSecret, error)
    
}

I didn't have an endpoint for the API call so I created this request for a token. This is the function I have at my API endpoint:

exports.createStripeToken = functions.https.onRequest(async (req, res) => {
var cardAddressCity = req.body.card.address_city;
var cardAddressCountry = req.body.card.address_country;
var cardAddressLine = req.body.card.address_line1;
var cardAddressProvince = req.body.card.address_state;
var cardAddressPostalCode = req.body.card.address_zip;
var cardHolderName = req.body.card.name;

var muid = req.body.muid;
var pkToken = req.body.pk_token;
var pkTokenInstrument = req.body.pk_token_instrument_name;
var pkTokenNetwork = req.body.pk_token_payment_network;
var pkTokenTransactionID =  req.body.pk_token_transaction_id;

const token = await stripe.tokens.create({
  card: {
    "address_city": cardAddressCity,
    "address_country": cardAddressCountry,
    "address_line1": cardAddressLine,
    "address_state": cardAddressProvince,
    "address_zip": cardAddressPostalCode,
    "name": cardHolderName
  },
  "muid": muid,
  "pk_token": pkToken,
  "pk_token_instrument_name": pkTokenInstrument,
  "pk_token_payment_network": pkTokenNetwork,
  "pk_token_transaction_id": pkTokenTransactionID 
});

res.send({
  id: token.id,
});

});

I'm not sure if this is the correct way, I can't find much on the internet about this at all.

I figured this was the parameters I seen in my api logs so I used the same ones and I also seen a rare post on gist.github of a guy making an API call similar to this one, but for some reason it still doesn't work at all.


Solution

  • Your statements/logs aren't being hit because Token creation internally in STPApplePayContext is failing. For background, STPApplePayContext does:

    1. Create a Token from the Apple Pay encrypted card details.

    2. Using the Token, creates a PaymentMethod object.

    3. Then triggers the didCreatePaymentMethod() delegate implementation.

    And step 1 is failing.

    Typically when I've seen a Token creation request 500, that typically means there might be a mismatch on the merchant ID used on XCode vs the certificate set up on Stripe account. Or it could be some combination of a PKPaymentNetwork not being supported on a Stripe account country.

    I would re-do the steps of setting up the merchant ID and Apple Pay certificate, ideally on a fresh project to do away with any confusion or conflicts etc.

    Since this was a 500, Stripe Support would be the right people to deal with that, as the error possibly lies on their end. I would provide them request IDs for your /v1/tokens creation request.