Skip to content

Instantly share code, notes, and snippets.

@stevegraham
Created May 8, 2018 14:20
Show Gist options
  • Save stevegraham/a5ff65543217d911227800a7eedd7bd2 to your computer and use it in GitHub Desktop.
Save stevegraham/a5ff65543217d911227800a7eedd7bd2 to your computer and use it in GitHub Desktop.
Teller payment example with signatures
require "net/https"
require "time"
require "base64"
require "uri"
require "securerandom"
# Load your private key
pkey = OpenSSL::PKey::RSA.new File.read("private_key.pem")
# Create new HTTP request
uri = URI.parse "https://api.teller.io/accounts/00000000-0000-0000-0000-000000000000/payments/#{SecureRandom.uuid}"
req = Net::HTTP::Put.new uri.request_uri
# Set the request body with the payment parameters
req.form_data = {bank_code: "00-00-00", account_number: "00000000", amount: "0.01"}
# Instantiate a OpenSSL digest
sha256 = OpenSSL::Digest.new("sha256")
# Set Date header
req["Date"] = Time.now.httpdate
# Set Digest header
base64 = Base64.strict_encode64 sha256.digest(req.body)
req["Digest"] = "SHA-256=#{base64}"
# Set the Authorization header using the user access token from the TAuth redirect
req["Authorization"] = "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Set your User-Agent string and any other headers you want to include (optional)
req["Accept"] = "application/json"
req["User-Agent"] = "Super Rad App/0.0.1"
# Create signing string
signing_string =
req.
each_header.
inject(["(request-target): #{req.method.downcase} #{req.path}"]) { |arr, (k,v)| arr << ["#{k.downcase}: #{v}"] }.
join("\n")
# Create list of headers included in signature
header_list = req.each_key.to_a.join(" ")
# Sign the signing string
signature = pkey.sign(sha256, signing_string)
# Construct and set the final Signature header
req["Signature"] = %Q(keyId="certificate",algorithm="rsa-sha256",headers="#{header_list}",signature="#{Base64.strict_encode64(signature)}")
# Make the request!
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.cert = OpenSSL::X509::Certificate.new File.read("certificate.pem")
http.key = pkey
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.request(req)
@sasili-adetunji
Copy link

@stevegraham I am getting an error with {"error":{"message":"The requested resource does not exist","code":"not_found"}} when trying to hit the endpoints to make payments

@savavel
Copy link

savavel commented May 9, 2018

@sasili-adetunji Check the bank account id you are sending from, the bank_code, account_number, amount and authorization token that you get after Tauth redirect as well as your certificates. Otherwise it will tell you the resource doesn't exist. I got the same error, double-checked these parameters and it works.

@sasili-adetunji
Copy link

@savavel @stevegraham Thanks. After checking the auth token, I changed the bearer token to the authorization token that I got after Tauth redirect and I got this error.
{"error":{"message":"1020: Session has timed out","code":"institution_error"}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment