I'm trying to create a recurring payment on Square, ala Stripe subscriptions. However, I am having trouble retrieving a customer's card information (specifically customer_card_id) to pass into Charge.
Our flow is such:
A customer visits to our store and subscribes to a membership, which we process via the point of sale app.
We continuously poll Square to retrieve payment information, and create membership records appropriately.
When the user's membership period expires, charge them for the next month's membership.
When researching RetrieveCustomer, I find that there is a cards property under Customer, but iterating through all the Customers under our account, they all have cards = None despite us having taken card payments via the point of sale app.
Also, looking at ListTransactions, there doesn't seem to be anything that might be customer_card_id. The IDs I see there are tender ID, location ID, and transaction ID. The card_fingerprint also looks promising but that doesn't seem right either, since a card can have both an ID and a fingerprint.
Am I missing something? Where might I find customer_card_id?
EDIT
Looks like I was dumb and my local instance of our application was just out of date with transactions from Square. After updating my data with customers we've processed since the last time I updated, customers with a non-None card property now show up. tristansokol's answer below is still valid however.
How do you process the first charge? You need to explicitly add the card on file, it won't be added by default from processing a transaction from a customer. See: https://squareup.com/help/us/en/article/5770-use-card-on-file-with-the-square-point-of-sale-app
Related
We're building a marketplace in NEAR. We have two smart contracts for token and marketplace. Same as NEAR example.
In our platform, we have successfully implemented below features:
Token mint (used contract method: nft_mint)
Token listing for sale at Fixed Price in marketplace (used contract methods: storage_deposit nft_approve)
Token purchase (used contract method: offer)
Apply creator royalty at mint time.
Apply service fee (Transaction fee of Marketplace) on each sale.
Everything is working fine.
Now, we would like to implement the Timed Auction Functionality
Creator can create NFT’s to be sold as an auction so that buyers can bid on them to get a higher price.
Method:- Sell to the highest bidder: where the highest bid wins at the end.
Making a bid on this kind of auction is like making an offer on a fixed-price listing. The seller can choose to accept it at any time, but the buyer will near of the amount of bid to create a bid.
Questions:
How we can implement the Timed Auction Functionality with Marketplace
Contract?
Do we have any documentation or example for the
Timed Auction Functionality?
Example of OpenSea's Timed Auction Functionality:
You can't do that directly from within a contract since the contract does not run all the time you will have to call function trough something like https://cron.cat/ or your own.
Contracts perceive time trough current execution so when a function is called env::block_timestamp_ms() within said fn would give us the current time of execution, you can subtract time from it to get some time in the past. We can do manual checks like is the time stamp past this than do that or the less accurate is the blockheight above certain threshold but all this will have to be executed within a function that needs to be called.
I will preface this post by saying that this is how I would go about solving this in a simple way. There are more complex solutions out there but I'll try and keep it relatively simple. (scroll to the bottom for a TLDR).
Here's a solution to the timed auction functionality. In the marketplace example that you posted, what you'll want to do is store two extra fields in the sale object indicating the desired length of the auction as well as the time when the sale was listed.
Whenever NFTs are put for sale (in the nft_on_approve function), you'll need to add the current block_timestamp (which will give you the number of nanoseconds since the Unix epoch). You'll also need to store the desired length of the auction which is up to you as to how you would like to implement that. It can be time in nanoseconds, milliseconds, seconds, days, either since the Unix epoch or the actual desired duration of the auction.
Once your sale object contains both these new fields, all you would need to do is whenever an offer is made, check if the current block timestamp is within the desired auction length. If it is, proceed, if it's not panic. Since the marketplace can't constantly be polling to see if the auction is finished, a common approach is to use the functionality I described above:
You either bid on the NFT before the timestamp or you didn't. If you did, your bid is accepted, if you don't, it panics.
At this point, there is no way for the marketplace to automatically transfer the NFT to the highest bidder the second the auction closes (due to the marketplace's inability to poll). My suggestion here would be to have a claim function that the highest bidder must call if they want the NFT transferred to them. You can get spicy with this and have timeouts whereby if it isn't claimed within 5 days, the original owner can claim it back but for the sake of simplicity, let's not get into that.
As for the bidding mechanic, there's many different ways you can do this. I'll go over one of the more simple approaches. Currently, when a sale is listed with sale conditions, the NFT can only be purchased for more than or equal to the price as shown here. What you'll want to do is store active bids in the sale object.
You'll need to store both the current highest bidder as well as their bid amount. This will be initialized to empty when the NFT is listed and then once an offer is made for less than the desired list price, it's considered a bid. Bids will only be added if they are less than the desired price and greater than the highest current bid. If the offer is more than the list price, the NFT is automatically sold and the purchase is processed.
Combining everything I've outlined so far in a TLDR:
What you would need to add as a minimum PoC to the sales object:
Store desired length of auction (in whatever format you want)
Store date of listing
Store current highest bidder
Store current highest bid
Listing mechanics:
When a sale is listed, set the date of listing and the desired length of the auction.
Offer mechanics:
make sure the attached deposit is greater than the current highest bid (if none, make sure it's >= 0).
If the attached deposit is greater than the list price, process the purchase. If it's not, add it as the current highest bid.
Make sure that the any offers are made within the desired length of the auction. If they aren't panic, if they are, you're good to go.
If somebody is outbid, make sure you refund them for their deposit!
Claim mechanics:
Claims can only be made if the auction time has passed. Only the highest bidder can claim the NFT. Once claimed, the purchase is processed.
I'm in the early stages of integrating Square payments. It makes sense in my application to allow users to save their card details, as we expect multiple small transactions. Square calls this feature 'cards on file'.
As part of this process you create a customer and a related card in Square's system; IDs for these will be held in my system and associated with my users; that way when they come to pay again they can select the option of using a card on file. The API to actually charge the card simply takes these two IDs and an amount.
What worries me is that my database is holding all the data necessary to charge a customer's card; I could write a script which just charges all of my customers an amount of money - naturally a hacker with access to my data could do the same thing.
I wasn't expecting to have this level of risk in my system - my assumption was that Square would have isolated me from this (via some sort of user challenge for missing data - e.g. the CCV number). It seems the safe option is to not use the 'card on file' feature and have the user re-enter every time.
Is this right, or have I completely misunderstood something here?
In order to charge a card, your Square access token is required along with the card ID. It's best practice to store that access token as an environment variable in order to limit the security risk. If someone gains access to the card IDs in your database, they won't be able to charge any of the cards without that access token that's associated with your developer account.
I did miss something - as any charge made on a customer's saved card is credited to my account (as configured in the Square portal), the only beneficiary of any fraudulent charge would be be me. A hacker could not get access to funds and therefore the risk is limited in scope.
Obviously if I was a fraudulent company there would be a risk to users - it seems the EU isn't happy with this and changes coming this year will require additional information to be captured from the user at the point of sale.
Strong Customer Authentication
Basically what I want to do is show a list of stored payment methods of the customer so they can pick an existing one instead of putting in credit card info.
I know I can store customerId and payment token in my server. But I need a way to present and map the token to some basic card info (such as Visa, last for digits, Name), so the user would know which is which. And upon user submitting the form, I need to know which token they've selected.
What's the best way of achieving this?
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
With a customer_id, you can call Braintree::Customer.find("customer_id") to get a Customer object, and then call customer.payment_methods to get the list of payment methods associated with that specific customer.
The list of attributes of each PaymentMethod object will differ depending on whether it is a credit card, PayPal account, or Apple or Android Pay Card. For example, you can find the attributes for a credit card payment method on this page.
Each PaymentMethod object will also have a token, so when the user selects one of the payment methods, you can use that token to create the transaction.
I have an app that uses Parse as its backend, and has Stripe integration. On Parse, I store a Stripe customer id on my User class, and I have a custom class that has a charge token associated with it, so that a customer can create a service request, and when a provider accepts and fulfills that request, they can have the charge be sent to their recipient id.
A user could cancel the service request, or a provider could show up to the user's property and find that the property is unserviceable for various reasons. In this event, we have a cancellation fee that the users are charged.
I want to make sure that if the cancellation fee is charged, it gets charged to the same card that the user used to request the service. I noticed that when I fetch all of the cards from a customer id, they always show up in the same order, but when I add a card, it doesn't always add it to the end of the array that gets returned when I fetch cards. So, if I just stored the index of the card, a user could add a new card, and it would possibly take the place of the one that was being charged for the service. If I charged a card based on the index for a cancellation, it could charge the incorrect card. Would it be PCI compliant to store the cardID used to create the charge token on the Parse object that contains information about the service, so when I call my functions to create cancellation charges, I'm charging the same card?
Thanks for anyone who can provide some information on this.
The only sensitive data that you want to avoid handling is your customers' credit card number and CVC; other than that, you're welcome to store any other information on your local machines.
As a good rule, you can store anything returned by our API. In particular, you would not have any issues storing the last four digits of your customer's card number or the expiration date for easy reference.
from: https://support.stripe.com/questions/what-information-can-i-safely-store-about-my-users-payment-information
Let's say that customer has single credit card (paymentMethod) bound to his account and he starts (buys) subscription to monthly plan with 30 day trial.
I would like to allow user to manage his credit card: delete it, add new (after deleting old card) and change it (delete+create new, actually).
The problem is that, AFAIK, when credit card is deleted then all subscriptions bound to it are also deleted. So theoretically user could delete his credit card just before trial expiration, add it again (same card) and "buy" same subscription again with another trial period.
Am I right? Is there anything I can do about it?
I work at Braintree. Feel free to reach out to support#braintreepayments.com with any further questions.
The easiest way to address this issue would be to not allow users to delete credit cards inside of the Vault, but only update their cards or cancel their subscriptions. Making a credit card update call means that your users can still change their card whenever they would like and the status of your subscription remains unchanged. For more information about how to update credit cards see the Braintree docs.
The other option would be to keep track of the uniqueNumberIdentifier of each credit card for each customer on your side. Then, before you create the subscription for a customer you can check the uniqueNumberIdentifier attribute of the payment method that you just created by reading it off the response and see if it matches any previous card associated with that customer. If yes, they are attempting to use the same card multiple times. The Braintree docs have more information about the attributes of the credit card object.