I want to get Customerid of Stripe After Saving Card I got STPToken .I am unable create customerid from STPToken From Swift. Please Help. Here is my code snippet.
let paymentConfig = STPPaymentConfiguration.init();
paymentConfig.requiredBillingAddressFields = STPBillingAddressFields.none;
paymentConfig.publishableKey = "pk_test_whRD827lMXvFb1MtY9T7bRzW"
let theme = STPTheme.default();
let addCardViewController = STPAddCardViewController.init(configuration: paymentConfig, theme: theme);
addCardViewController.delegate = self;
let navigationController = UINavigationController(rootViewController: addCardViewController);
self.present(navigationController, animated: true, completion: nil);
func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: #escaping STPErrorBlock) {
print(token)
dismiss(animated: true)
}
You can not get customer id from the client. It should be generated on your server. Here is the reference for your server to generate customer,
https://stripe.com/docs/api/dotnet#create_customer
You should have an API to send stptoken on your server and then your server should create a customer and return the customerId in the response.
Related
Apple Pay token contains wrong transactionAmount info. E.g if the transaction amount is $1.10, on iOS device, Apple Pay screen stills show correct amount but paymentToken returns 110 when decrypted
I used this library to decrypt Apple Pay token using my own public-private key pair
https://github.com/sidimansourjs/applepay-token
My sample code
class ViewController: UIViewController {
...
#IBAction func payBtn(_ sender: UIButton) {
do {
let paymentItem = PKPaymentSummaryItem.init(label: "Test item", amount: NSDecimalNumber(value: 1.10))
let paymentNetworks = [PKPaymentNetwork.amex, .discover, .masterCard, .visa]
if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {
let request = PKPaymentRequest()
request.currencyCode = "SGD" // 1
request.countryCode = "SG" // 2
request.merchantIdentifier = "merchant.com.xxxxx" // 3
request.merchantCapabilities = PKMerchantCapability.capability3DS // 4
request.supportedNetworks = paymentNetworks // 5
request.paymentSummaryItems = [paymentItem] // 6
guard let paymentVC = PKPaymentAuthorizationViewController(paymentRequest: request) else {
displayDefaultAlert(title: "Error", message: "Unable to present Apple Pay authorization.")
return
}
paymentVC.delegate = self
self.present(paymentVC, animated: true, completion: nil)
} else {
displayDefaultAlert(title: "Error", message: "Unable to make Apple Pay transaction.")
}
} catch {
print(error.localizedDescription)
}
}
}
extension ViewController: PKPaymentAuthorizationViewControllerDelegate {
func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
dismiss(animated: true, completion: nil)
}
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: #escaping (PKPaymentAuthorizationResult) -> Void) {
let token = String(data: payment.token.paymentData, encoding: .utf8)
let utf8str = token!.data(using: .utf8)
if let base64Encoded = utf8str?.base64EncodedString()
{
print("Encoded: \(base64Encoded)")
//Send token to backend server to decrypt
}
}
}
I discovered this when try to make payment request to Adyen (a payment gateway). Request must contain both amount field and paymentToken field but was never successful because amount in amount and paymentToken is mis-matched. Then I tried amount 110 instead of 1.10 then request was success, but ironically in Adyen dashboard somehow it still understood transaction amount was $1.10
I expected transactionAmount in Apple Pay token to be 1.10
Please help to explain why there's this difference in Apple Pay amount shown on device and in token
Found answer as suggested by #Don
Singapore Dollar SGD's smallest unit is cent, which is 1/100 of a dollar. Therefore I need to convert dollar amount into cent integer by multiply with 100. Then, use this value when send over to Adyen
I'm currently working on integrating Stripe into my iOS application via firebase cloud functions. I'm running into a weird problem where when I try to add a card It tells me that my API key is missing when I definitely configured it in my cloud functions.
One thing I noticed is on the client side if I don't include a STPPaymentConfiguration(), then the code works correctly and a payment source gets added to firebase and stripe. Am I missing something here?
I think it's something on the front end side that I'm not quite grasping because with
let addCardViewController = STPAddCardViewController()
my code works fine and as it should but now the view controller doesn't have billing address options.
My front end swift code:
#objc func addPaymentPressed(_ sender:UIButton) {
// Setup add card view controller
let config = STPPaymentConfiguration()
config.requiredBillingAddressFields = .full
let addCardViewController = STPAddCardViewController(configuration: config, theme: theme.stpTheme)
//Creating VC without configuration and theme works just fine
//let addCardViewController = STPAddCardViewController()
addCardViewController.delegate = self
let navigationController = UINavigationController(rootViewController: addCardViewController)
navigationController.navigationBar.stp_theme = theme.stpTheme
present(navigationController, animated: true, completion: nil)
}
func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) {
// Dismiss add card view controller
dismiss(animated: true)
}
func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: #escaping STPErrorBlock) {
dismiss(animated: true)
let cardObject = token.allResponseFields["card"]
print("Printing Strip Token:\(token.tokenId)")
CustomerServices.instance.addPaymentToDB(uid: currentUserId, payment_token: token.tokenId, stripe_id: token.stripeID, cardInfo: cardObject as Any) { (success) in
if success {
print("successfully added card info to subcollection!")
} else {
print("TODO: add error message handler")
}
}
}
My Cloud function code:
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const stripe = require('stripe')(functions.config().stripe.token);
const currency = functions.config().stripe.currency || 'USD';
// Add a payment source (card) for a user by writing a stripe payment source token to database
exports.addPaymentSource = functions.firestore
.document('Customers/{userId}/paymentSources/{paymentId}')
.onWrite((change, context) => {
let newPaymentSource = change.after.data();
let token = newPaymentSource.payment_token;
return admin.firestore().collection("Customers").doc(`${context.params.userId}`).get()
.then((doc) => {
return doc.data().customer_id;
}).then((customer) => {
return stripe.customers.createSource(customer, {"source" : token});
});
});
When adding configuration to me STPAddCardViewController it gives me an "You did not provide an API key" error.
The issue looks to be that you are creating a new instance of STPPaymentConfiguration (which does not have your Stripe publishable key set to it), instead of using the shared instance (which you probably set your publishable key elsewhere in your code).
You need to make this change:
let config = STPPaymentConfiguration.shared()
The reason just instantiating let addCardViewController = STPAddCardViewController() works is because the initializer actually uses STPPaymentConfiguration.shared() for its configuration.
I got the same error. I was creating an instance of STPAPIClient() and setting publishableKey key.
let client = STPAPIClient()
client.publishableKey = ""
The right way is to use the shared instance of STPAPIClient()
STPAPIClient.shared().publishableKey = ""
let cardParams = STPCardParams()
cardParams.number = cardTextField.cardNumber
cardParams.expMonth = (cardTextField.expirationMonth)
cardParams.expYear = (cardTextField.expirationYear)
cardParams.cvc = cardTextField.cvc
STPAPIClient.shared().createToken(withCard: cardParams) { (token: STPToken?, error: Error?) in
guard let token = token, error == nil else {
print(error?.localizedDescription)
}
}
I successfully call DropIn view from Braintree SDK. The BTDropInRequest settings should display three items:
PayPal
Credit Cards
Apple Pay
But for some reason in DropIn view renders only two items instead of three:
PayPal
Credit Cards
What I did wrong?
Preparation:
All certificates are created and uploaded
Apple Pay is enabled on the project capabilities
Merchant ID is added
The device on which I do testing is supported Apple Pay
Here is a code of method which does request:
func showDropIn(clientTokenOrTokenizationKey: String) {
BTUIKAppearance.darkTheme()
let request = BTDropInRequest()
let canMakePayments = PKPaymentAuthorizationViewController.canMakePayments() && PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: [.amex, .visa, .masterCard])
request.applePayDisabled = !canMakePayments
request.cardDisabled = false
let dropIn = BTDropInController.init(authorization: clientTokenOrTokenizationKey, request: request) { (controller, result, error) in
if (error != nil) {
print("ERROR")
} else if (result?.isCancelled == true) {
print("CANCELLED")
} else if let result = result{
switch result.paymentOptionType {
case .applePay ,.payPal,.masterCard,.discover,.visa:
if let paymentMethod = result.paymentMethod {
controller.dismiss(animated: true, completion: nil)
} else {
controller.dismiss(animated: true, completion: {
self.braintreeClient = BTAPIClient(authorization: clientTokenOrTokenizationKey)
let paymentRequest = self.paymentRequest()
if let vc = PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)
as PKPaymentAuthorizationViewController?
{
vc.delegate = self
self.present(vc, animated: true, completion: nil)
} else {
print("Error: Payment request is invalid.")
}
})
}
default:
print("error")
controller.dismiss(animated: true, completion: nil)
}
}
}
self.present(dropIn!, animated: true, completion: nil)
}
Base on a document from Braintree, you should complete the Apple Pay integration and the customer's device and card type are supported.
https://developers.braintreepayments.com/guides/drop-in/setup-and-integration/ios/v4#apple-pay
Also, take note at this point
If using a client token with a customer id, the Apple Pay card will
not automatically be vaulted. You can use the payment method nonce to
create a payment method on your server.
I'm trying to develop an app, that take a number from a variable then open in "Messages" app with (1500) in the field To: and the variable value in Text Messages field like this
I tried this answer how to open an URL in Swift3 and Swift: How to open a new app when uibutton is tapped but i didn't figure out the URL for Messages app
what should I use? Big thanks.
use this
if MFMessageComposeViewController.canSendText() == true{
let recipients:[String] = ["1500"]
var messageController = MFMessageComposeViewController()
//messageController.messageComposeDelegate = self // implement delegate if you want
messageController.recipients = recipients
messageController.body = "Your_text"
self.present(messageController, animated: true, completion: nil)
}
You need to import "MessageUI" to your class and use the below code.
func sendMessages() {
if MFMessageComposeViewController.canSendText() == true {
let recipients:[String] = ["9895249619"]
let messageController = MFMessageComposeViewController()
messageController.messageComposeDelegate = self
messageController.recipients = recipients
messageController.body = "Your_message_text"
self.present(messageController, animated: true, completion: nil)
} else {
//handle text messaging not available
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
controller.dismiss(animated: true, completion: nil)
}
I'm trying to setup Apple Pay on my app, but I don't have an iPhone 6 with me at the moment. So I'm trying to get everything up and running with the simulator before I can go buy one, or try to get someone to lend one to me.
Anyway, I got to the point of actually showing the ApplePay view controller:
But when I tap on "Pay with Passcode" nothing happens, so I can't go any further and finish testing everything with the server.
Here are the relevant parts of my code:
class PaymentVC: UIViewController,PKPaymentAuthorizationViewControllerDelegate {
#IBAction func onPaymentSubmit(sender: AnyObject) {
if PKPaymentAuthorizationViewController.canMakePaymentsUsingNetworks(supportedPaymentNetworks) {
let applePayMerchantID = "merchant.com.id"
let request = PKPaymentRequest()
request.merchantIdentifier = applePayMerchantID
request.supportedNetworks = supportedPaymentNetworks
request.merchantCapabilities = PKMerchantCapability.Capability3DS
request.countryCode = "US"
request.currencyCode = "USD"
request.paymentSummaryItems = [
PKPaymentSummaryItem(label: "Custom Order", amount: NSDecimalNumber(float: total))
]
let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request)
applePayController.delegate = self
self.presentViewController(applePayController, animated: true, completion: nil)
}
}
//MARK: Apple Pay
func paymentAuthorizationViewController(controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, completion: (PKPaymentAuthorizationStatus) -> Void) {
}
func paymentAuthorizationViewControllerDidFinish(controller: PKPaymentAuthorizationViewController) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
}
Any idea what might be wrong?
You need to return a payment status in paymentAuthorizationViewController. You'll see that delegate method has a completion handler that you must call to indicate whether you were able to process the payment successfully or not.