Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPP backend for receiving payments and making payouts #817

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
},
"css.validate": false,
"less.validate": false,
"scss.validate": false
"scss.validate": false,
"cSpell.words": [
"emailaddress"
]
}
8 changes: 8 additions & 0 deletions core/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"cSpell.words": [
"emailaddress",
"idempotency",
"Nestru",
"uuid"
]
}
6 changes: 6 additions & 0 deletions core/architecture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Architecture

## Archimate

Archimate files can be viewed and edited using Archi (download [here](https://www.archimatetool.com/)).

607 changes: 607 additions & 0 deletions core/architecture/core.archimate

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions core/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,11 @@ unless is_nil(bundle) do
end

import_config "#{config_env()}.exs"

if Mix.env() == :dev do
config :mix_test_watch,
clear: true

config :mix_test_watch,
exclude: [~r/\.#/, ~r{priv/repo/migrations}, ~r/assets\/.*/]
end
5 changes: 5 additions & 0 deletions core/config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ if config_env() == :prod do

config :logger, level: System.get_env("LOG_LEVEL", "info") |> String.to_existing_atom()

config :core,
opp_client_options: [
auth: {:bearer, System.fetch_env!("OPP_API_KEY")}
]

if sentry_dsn = System.get_env("SENTRY_DSN") do
config :sentry,
dsn: sentry_dsn,
Expand Down
175 changes: 175 additions & 0 deletions core/lib/opp_client.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
defmodule OPPClient do
use OPPClient.Helper

defmodule OPPResponses do
end

@base_url "https://api-sandbox.onlinebetaalplatform.nl/v1"

# @api_key "79eeea74cb5685779ac17f5758ddc5e0"

def new(opts \\ []) do
[
base_url: @base_url
]
|> Keyword.merge(opts)
|> Req.new()
end

def_req(:post, "/merchants",
type: [
type: {:in, ["consumer", "business"]}
],
country: [
# TODO: Download ISO list on build:
# https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/all/all.json
type: {:in, ["nld"]},
required: true
],
emailaddress: [
type: :string,
required: true
],
notify_url: [
type: :string,
required: true
]
)

def_req(:get, "/merchants/{{merchant_uuid}}")

def_req(:post, "/transactions",
merchant_uid: [type: :string, required: true],
locale: [type: {:in, ["nl", "en", "fr", "de"]}],
total_price: [type: :pos_integer, required: true],
products: [
type:
{:list,
{:map,
[
name: [type: :string, required: true],
quantity: [type: :pos_integer, required: true],
price: [type: :pos_integer, required: true]
]}},
required: true
],
return_url: [type: :string, required: true],
notify_url: [type: :string, required: true],
metadata: [type: :map]
)

def_req(:post, "/merchants/{{merchant_uid}}/withdrawals",
amount: [type: :pos_integer, required: true],
currency: [type: :string],
partner_fee: [type: :pos_integer],
notify_url: [type: :string, required: true],
description: [type: :string, required: true],
reference: [type: :string],
metadata: [type: :map]
)

def_req(:post, "/charges",
type: [type: {:in, ["balance"]}, required: true],
amount: [type: :pos_integer, required: true],
currency: [type: :string],
description: [type: :string],
payout_description: [type: :string],
to_owner_uid: [type: :string, required: true],
from_owner_uid: [type: :string, required: true],
metadata: [type: :string]
)

# create
# retrieve
# update
# delete

# type string Merchant type. One of:
# consumerbusiness
# country string Country code of the merchant,
# use ISO 3166-1 alpha-3 country code.
# locale string The language in which the text on the verification screens is being displayed and tickets are sent. Default is en
# One of:
# nl en fr de
# name_first string First name of the merchant. ( CONSUMER ONLY! )
# name_last string Last name of the merchant. ( CONSUMER ONLY! )
# is_pep boolean Whether or not the merchant is a PEP. This will mark the contact that is automatically created as a PEP. ( CONSUMER ONLY! )
# coc_nr string Chamber of Commerce number of the merchant.
# up to 45 characters
# nullable
# ( BUSINESS ONLY! )
# vat_nr string Value added tax identification number.
# up to 45 characters
# ( BUSINESS ONLY! )
# legal_name string (Business) Name of the merchant.
# up to 45 characters
# legal_entity string Business entity of the merchant. One of the legal_entity_code from the legal entity list ( BUSINESS ONLY! )
# trading_names array Array with one or more trading names.

# name
# string

# Trading name.
# emailaddress string Email address of the merchant.
# Must be unique for every merchant.
# phone string Phone number of the merchant.
# settlement_interval string The settlement interval of the merchant. Default is set contractually. Can only be provided after agreement with OPP.
# One of:
# daily weekly monthly yearly continuous
# notify_url string URL to which the notifications of the merchant will be sent.
# return_url string URL to which the merchant will be directed when closing the verification screens.
# metadata object with key-value pairs Additional data that belongs to the merchant object.
# addresses array Address array of the merchant with name/value pairs.

# 200 OK Success
# 400 Bad Request Missing parameter(s)
# 401 Unauthorized Invalid or revoked API key
# 404 Not Found Resource doesn't exist
# 409 Conflict Conflict due to concurrent request
# 410 Gone Resource doesn't exist anymore
# 50X Server Errors Temporary problem on our side

# api_key (env var)

# API Status

# Example request - Status check

# curl https://api-sandbox.onlinebetaalplatform.nl/status \
# -H "Authorization: Bearer {{api_key}}"

# Example response

# {
# "status": "online",
# "date": 1611321273
# }

# Idempotency-Key: {key}

# Pagination

# Example request - Retrieve page 2 of the transactions list:

# curl https://api-sandbox.onlinebetaalplatform.nl/v1/transactions?page=2&perpage=10 \
# -H "Authorization: Bearer {{api_key}}"

# Example response:

# {
# "livemode": true,
# "object": "list",
# "url": "/v1/transactions",
# "has_more": true,
# "total_item_count": 259,
# "items_per_page": 10,
# "current_page": 2,
# "last_page": 26,
# "data": []
# }

# When retrieving lists of objects, OPP creates pages to keep the transferred objects small. Use the pagination functionality to navigate when sorting through many results. The pages can be switched by adding the following parameters to the GET call:
# Parameter Description
# page integer The number of the current page.
# perpage integer The limit of objects to be returned. Limit can range between 1 and 100 items.
end
78 changes: 78 additions & 0 deletions core/lib/opp_client/get_merchants_by_merchant_uuid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "https://docs.onlinepaymentplatform.com/#create-merchant",
"type": "object",
"properties": {
"uid": {
"type": "string",
"minLength": 1
},
"object": {
"type": "string",
"minLength": 1
},
"created": {
"type": "number"
},
"updated": {
"type": "number"
},
"status": {
"type": "string",
"minLength": 1
},
"compliance": {
"type": "object",
"properties": {
"level": {
"type": "number"
},
"status": {
"type": "string",
"minLength": 1
},
"overview_url": {
"type": "string",
"minLength": 1
}
},
"required": [
"level",
"status",
"overview_url"
]
},
"type": {
"type": "string",
"minLength": 1
},
"coc_nr": {
"type": "object",
"properties": {}
},
"name": {
"type": "string",
"minLength": 1
},
"phone": {
"type": "string",
"minLength": 1
},
"country": {
"type": "string",
"minLength": 1
}
},
"required": [
"uid",
"object",
"created",
"updated",
"status",
"compliance",
"type",
"name",
"phone",
"country"
]
}
Loading