条带付款上下文未使用Swift 3&amp ;;连接到后端API的NodeJS

时间:2016-12-02 20:44:29

标签: ios node.js swift xcode stripe-payments

我正在使用Xcode 8,Swift 3,NodeJS和Atom

关注Stripe的Standard iOS Integration Guide https://stripe.com/docs/mobile/ios/standard我在调用paymentContextDidChange时收到一个简单的本地化错误。

当用户准备选择付款时调用此方法,这反过来允许我调用Stripe的预建UI STPPaymentMethodsViewController。但我无法调用该功能。相反,我调用的方法didFailToLoadWithError通常在网络连接错误时发生,或者连接到我的后端时出现问题。

这是我在Xcode中的客户端代码:

// MARK: - STPPaymentContextDelegate
func paymentContextDidChange(_ paymentContext: STPPaymentContext) {
    if let paymentMethod = paymentContext.selectedPaymentMethod {
        self.paymentRow.detail = paymentMethod.label
    }
    else {
        self.paymentRow.detail = "Select Payment"
    }
    self.totalRow.detail = self.numberFormatter.string(from: NSNumber(value: Float(self.paymentContext.paymentAmount)/100))!
}

func paymentContext(_ paymentContext: STPPaymentContext, didCreatePaymentResult paymentResult: STPPaymentResult, completion: @escaping STPErrorBlock) {
    MyAPIClient.sharedClient.completeCharge(paymentResult, amount: paymentContext.paymentAmount, completion: completion)
}

func paymentContext(_ paymentContext: STPPaymentContext, didFinishWith status: STPPaymentStatus, error: Error?) {
    let title: String
    let message: String
    switch status {
    case .error:
        title = "Error ⚠️"
        message = error?.localizedDescription ?? "☹️"
    case .success:
        title = "Success "
        message = "You Have Successfully Made a Charge "
    case .userCancellation:
        return
    }
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    let action = UIAlertAction(title: "Heard", style: .default, handler: nil)
    alert.addAction(action)
    self.present(alert, animated: true, completion: nil)
}

func paymentContext(_ paymentContext: STPPaymentContext, didFailToLoadWithError error: Error) {

    let alertController = UIAlertController(
        title: "Error ⚠️",
        message: error.localizedDescription,
        preferredStyle: .alert
    )
    let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { action in
        _ = self.navigationController?.popViewController(animated: true)
    })
    let retry = UIAlertAction(title: "Retry", style: .default, handler: { action in
        self.paymentContext.retryLoading()
    })
    alertController.addAction(cancel)
    alertController.addAction(retry)
    self.present(alertController, animated: true, completion: nil)
}

这是我在XCode中的API适配器

class MyAPIClient: NSObject, STPBackendAPIAdapter {

static let sharedClient = MyAPIClient()
let session: URLSession
var baseURLString: String? = nil
var defaultSource: STPCard? = nil
var sources: [STPCard] = []

override init() {
    let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = 5
    self.session = URLSession(configuration: configuration)
    super.init()
}

func decodeResponse(_ response: URLResponse?, error: NSError?) -> NSError? {
    if let httpResponse = response as? HTTPURLResponse
        , httpResponse.statusCode != 200 {
        return error ?? NSError.networkingError(httpResponse.statusCode)
    }
    return error
}


func retrieveCustomer(_ completion: @escaping STPCustomerCompletionBlock) {
    let userInfo = "Could Not Retrieve Stripe Customer"
    guard let key = Stripe.defaultPublishableKey(), !key.contains("#")
        else {
        let error = NSError(domain: StripeDomain, code: 50, userInfo: [NSLocalizedDescriptionKey: "\(userInfo)"])
        completion(nil, error)
            print("\(userInfo)")
        return
    }
    guard let baseURLString = baseURLString, let baseURL = URL(string: baseURLString)
        else {return}

    let path = "/customer"
    let url = baseURL.appendingPathComponent(path)

    let request = URLRequest.request(url, method: .GET, params: [:])
    let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
        DispatchQueue.main.async {
            let deserializer = STPCustomerDeserializer(data: data, urlResponse: urlResponse, error: error)
            if let error = deserializer.error {
                completion(nil, error)
                return
            } else if let customer = deserializer.customer {
                completion(customer, nil)
            }
        }
    }
    task.resume()
}


func attachSource(toCustomer source: STPSource, completion: @escaping STPErrorBlock) {
    guard let baseURLString = baseURLString, let baseURL = URL(string: baseURLString)
        else {
        if let token = source as? STPToken, let card = token.card {
            self.sources.append(card)
            self.defaultSource = card
        }
        completion(nil)
        return
    }
    let path = "/customer/sources"
    let url = baseURL.appendingPathComponent(path)
    let params = ["source": source.stripeID]

    let request = URLRequest.request(url, method: .POST, params: params as [String : AnyObject])
    let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
        DispatchQueue.main.async {
            if let error = self.decodeResponse(urlResponse, error: error as NSError?) {
                completion(error)
                return
            }
            completion(nil)
        }
    }
    task.resume()
}


func selectDefaultCustomerSource(_ source: STPSource, completion: @escaping STPErrorBlock) {
    guard let baseURLString = baseURLString, let baseURL = URL(string: baseURLString)
        else {
        if let token = source as? STPToken {
            self.defaultSource = token.card
        }
        completion(nil)
        return
    }
    let path = "/customer/default_source"
    let url = baseURL.appendingPathComponent(path)
    let params = ["source": source.stripeID]

    let request = URLRequest.request(url, method: .POST, params: params as [String : AnyObject])
    let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
        DispatchQueue.main.async {
            if let error = self.decodeResponse(urlResponse, error: error as NSError?) {
                completion(error)
                return
            }
            completion(nil)
        }
    }
    task.resume()
}

// MARK: - Complete Charge
func completeCharge(_ result: STPPaymentResult, amount: Int, completion: @escaping STPErrorBlock) {
    let userInfo = "Could Not Complete Stripe Customer Charge"
    guard let baseURLString = baseURLString, let baseURL = URL(string: baseURLString)
        else {
        let error = NSError(domain: StripeDomain, code: 50, userInfo: [NSLocalizedDescriptionKey: "\(userInfo)"])
        completion(error)
        return
    }
    let path = "charge"
    let url = baseURL.appendingPathComponent(path)
    let params: [String: Any] = ["source": result.source.stripeID as Any, "amount": amount as Any]

    let request = URLRequest.request(url, method: .POST, params: params as [String : AnyObject])
    let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
    DispatchQueue.main.async {
        if let error = self.decodeResponse(urlResponse, error: error as NSError?) {
            completion(error)
            return
        }
        completion(nil)
    }
}
task.resume()
}

}

这是我在NodeJS中的后端代码

const stripe = require('stripe')('sk_test_....');
const express = require('express');
const app = express();

// Request Token API
const token = request.body.stripeToken;

// Retrieve Customer API
app.get('/customer', function(request, response) {

  var customerId = 'cus_...';
  stripe.customers.retrieve(customerId, function(err, customer) {
    if (err) {
      response.status(402).send('Error retrieving customer.');
      console.log('Could not retrieve customer');
    } else {
      response.json(customer);
      console.log('Success retrieving customer');
    }
  })
});

// Attach a new payment source API
app.post('/customer/sources', function(request, response) {

  var customerId = 'cus_...';
  stripe.customers.createSource(customerId, {
    source: request.body.source
  }, function(err, source) {
    if (err) {
      response.status(402).send('Error attaching source.');
      console.log('Could not attach new payment source');
    } else {
      response.status(200).end();
  console.log('Success attaching new payment source');
    }
  });
});

// Select a new default payment source API
app.post('/customer/default_source', function(request, response) {

  var customerId = 'cus_...';
  stripe.customers.update(customerId, {
    default_source: request.body.defaultSource
  }, function(err, customer) {
    if (err) {
      response.status(402).send('Error setting default source.');
      console.log('Could not select default payment source');
    } else {
      response.status(200).end();
      console.log('Success selecting default payment source');
    }
  });
});

非常感谢任何帮助。

0 个答案:

没有答案