FoxPro Programming
Collecting payments using Stripe?
Gravatar is a globally recognized avatar based on your email address. Collecting payments using Stripe?
  Bruce Rowe
  All
  Dec 3, 2020 @ 10:48pm

We have a new customer who wants to use their Stripe account. I have some code, for basic functions. But, Stripe is balking about sending credit card numbers directly to Stripe. They want me to do an integration using their Stripe.js, Stripe mobile bindings, or Stripe Elements.

Has anyone here ever built this kind of integration?

Thanks.

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Rick Strahl
  Bruce Rowe
  Dec 4, 2020 @ 01:26am

I think Stripe doesn't support non-browser/mobile integrations as their authentication and validation runs through proprietary APIs and key combos. Unless something has changed it has to go through a supported interface which is Browser or Mobile libraries. You can't easily bypass those because there are embedded keys and validation algorithms that you can't duplicate easily.

There are dedicated SDKs for various platforms - including .NET which you can use from FoxPro via wwDotnetBridge, but I think those SDKs are used primarily to pick up processed result info and nonces, set up auth keys etc. but they don't actually allow sending.

I think they do this to offload the PCI requirements to the Stripe servers and so that the actual CC data cannot be captured locally.

What I've done in the past in a similar environment (Auth.NET's non-offline library) is use a WebBrowser control instance with a server hosted Web page to do the actual processing and then capture the results with the .NET SDK. It's messy but that works.

For offline processing there are other choices. Auth.NET has true offline SDKs as does BrainTree. But keep in mind that if you use those your are not legally PCI compliant unless you go through an audit.

Just as an aside - some time ago BrainTree which I use ratcheted up the requirements for processing too to the point where it was just not feasible to run offline processing any longer. While I rarely need offline capabilities, the few times I do need to create an order from scratch I actually have to do it online. Once authorized the SDKs allow access of the validated and stripped of original submission data results.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Michael B
  Bruce Rowe
  Dec 5, 2020 @ 09:59am

I have implemented an older version of stripe inside of my WWWC platform. It works similarly to paypal's PCI compliant js implementation. It's not that difficult to make happen if you are familiar with rest based web service implementations.

I have on this weeks to-do list to upgrade the implemetation as the UI is much nicer than it was.

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Rick Strahl
  Michael B
  Dec 5, 2020 @ 01:43pm

Web based is a totally different story - that can totally be done with Web Connection (or any other Web framework) since it's basically HTML/JavaScript.

Offline processing is the issue that's not easily addressed. AFAIK with Stripe there's no way to do that without some online component that runs on a DNS visible site that's public that Stripe can call back to. This can be done in combination with classic desktop apps that use a browser window (or external browser) to drive the CC processing online and then pick up the processing codes for later processing via the Stripe APIs, but this is a pretty painful process. Done this for a few customers and it's time consuming to build since it involves multiple apps and various messaging pipelines.

FWIW, I think this is the way to go simply because the risk of PCI non-compliance (for all but deep budget orgs) of managing CC cards is just too great. Offline processing requires at least handling CC data locally though so with that you can't be PCI-less anyway so that's an issue.

FWIW, I've not done this with Stripe, but BrainTree uses a similar approach. For my business any offline processing that happens (where somebody calls in a CC which surprisingly still happens) I have an online form I use to fill in the info and process it there. Reality is that it's easier to have the customer do that themselves, but alas some people still call.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Bruce Rowe
  Rick Strahl
  Dec 5, 2020 @ 06:26pm

The panic is over. Our customer called Stripe. He had to promise not to sue them. Then he had to send a test invoice. Finally, they switched him to "Dashboard - Manual Entry." Stripe worked again.

I still need to build a javascript interface to submit cards. But, I can do it at a more leisurely pace.

Bruce

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Michael B
  Bruce Rowe
  Mar 9, 2021 @ 03:04pm

Bruce - did you ever build your js ui ?

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Bruce Rowe
  Michael B
  Mar 10, 2021 @ 11:37am

No, I did not create any new UI for Stripe. I did discover that there is a question on their web site that asks you why you want to use the older interface. If you give them a reasonable answer, they let you use that interface.

I will be creating a different interface though. We already have an eCommerce interface that uses the javascript API. What I am going to do is call that interface through the wwWebBrowser control. I will enter the information there and it will go directly to Stripe.

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Michael B
  Bruce Rowe
  Mar 10, 2021 @ 04:25pm

I discovered today that my old version of Stripe integration was not rendering well on mobile, so I decided to RTFM and naturally I got stuck.

I am hoping that Rick might see this and lend a helping hand.

This is the sample code in Python. I used Python because its easily read. They of course support .Net which might be a way to get this done if all else fails.

session = stripe.checkout.Session.create(
  payment_method_types=['card'],
  line_items=[{
    'price_data': {
      'product': '{{PRODUCT_ID}}',
      'unit_amount': 1500,
      'currency': 'usd',
    },
    'quantity': 1,
  }],
  mode='payment',
  success_url='https://example.com/success',
  cancel_url='https://example.com/cancel',
)

I have attempted to create a JSON representation of what I see in their docs.

{
	"payment_method_types": "card",
	"line_items": [
{
	"price_data": {
		"product": "EBR1047XPR - 2008 Mercedes C300 Brake Rotor",
		"unit_amount": 7685,
		"currency": "usd"
	},
	"quantity": 1
}],
	"mode": "payment",
	"cancel_url": "https://michael.abc.com/shoppingcart.wws?invpk=9159937&action=RETURNURL",
	"return_url": "https://michael.abc.com/stripeapi.wws?invpk=9159937&action=RETURNURL"
}

Which when submitted returns this


{
  "error": {
    "code": "parameter_unknown",
    "doc_url": "https://stripe.com/docs/error-codes/parameter-unknown",
    "message": "Received unknown parameters: {\r\n\t\"payment_method_types\": \"card\",\r\n\t\"line_items\": , action",
    "param": "{\r\n\t\"payment_method_types\": \"card\",\r\n\t\"line_items\": ",
    "type": "invalid_request_error"
  }
}

The stripe support teams said 'we only support the languages you see in the docs' so clearly not helpful.

I should mention this is not a security issue as I started having auth issues on the onset, but resolved them easily.

I am posting like this

loHttp = Createobject("wwHttp")
*loHTTP.nHttpPostMode = 4  && breaks it
*loHttp.cContentType = "application/json" && breaks it
loHttp.AddHeader("Authorization","Bearer " + lcStripeSecretKey)  && base64 encoding
loHttp.AddPostKey("",tcJson)
_cresult = lohttp.HttpPost(lcUrl)

On a final note, Stripe has a log that you can see your request and response. Checkout below how they see my request body.

{
  "{
	"payment_method_types": "card",
	"line_items": ": {
    "
{
"price_data":
{
"product": "EBR1047XPR - 2008 Mercedes C300 Brake Rotor",
"unit_amount": 7685,
"currency": "usd"
},
"quantity": 1
}": {
      ",
	"mode": "payment",
	"cancel_url": "https://michael.sophio.com/shoppingcart.wws",
	"return_url": "https://michael.sophio.com/stripeapi.wws"
}": null
    }
  }
}
Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Bruce Rowe
  Michael B
  Mar 10, 2021 @ 09:45pm

Relax. Rick sees everything. He's really the best one to help you.

Gravatar is a globally recognized avatar based on your email address. re: Collecting payments using Stripe?
  Michael B
  Michael B
  Mar 11, 2021 @ 05:36am

Well some good news, I have saved Rick from wasting his time.

As it turns out, the solution to working with Stripe and WWWC was quite simple. Here is some sample code to get you started.

lcUrl = [https://api.stripe.com/v1/checkout/sessions]	
loHttp = Createobject("wwHttp")
loHTTP.nHttpPostMode = 1 
loHttp.AddHeader("Authorization","Bearer " + lcStripeSecretKey) 
loHttp.AddPostKey("payment_method_types[]",[card])
loHttp.AddPostKey("line_items[][price_data][product]",[SKU123])
loHttp.AddPostKey("line_items[][price_data][unit_amount]",[100])
loHttp.AddPostKey("line_items[][price_data][currency]",[usd])
loHttp.AddPostKey("mode",'payment')
loHttp.AddPostKey("success_url",lcReturnUrl)
loHttp.AddPostKey("cancel_url",lcCancelUrl)
_cresult = lohttp.HttpPost(lcUrl)

ps: For this to work straightaway, you must have a product setup in Stripe with a value of SKU123. The point of this sample code is that you can use simple AddPostKey to interact with the stripe api.

© 1996-2021