Start payments

This commit is contained in:
Adrian Woźniak 2022-12-01 17:39:06 +01:00
parent 605bf812a1
commit 1d775e3e1a
27 changed files with 1409 additions and 251 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ bazzar.toml
node_modules
web/dist
web/tmp
adapters

773
Cargo.lock generated
View File

@ -246,6 +246,15 @@ dependencies = [
"syn",
]
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -287,6 +296,12 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "ambient-authority"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec8ad6edb4840b78c5c3d88de606b22252d552b55f3a4699fbb10fc070ec3049"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -361,7 +376,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi 0.3.9",
]
@ -576,6 +591,71 @@ dependencies = [
"bytes",
]
[[package]]
name = "cap-fs-ext"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b0e103ce36d217d568903ad27b14ec2238ecb5d65bad2e756a8f3c0d651506e"
dependencies = [
"cap-primitives",
"cap-std",
"io-lifetimes",
"windows-sys 0.36.1",
]
[[package]]
name = "cap-primitives"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af3f336aa91cce16033ed3c94ac91d98956c49b420e6d6cd0dd7d0e386a57085"
dependencies = [
"ambient-authority",
"fs-set-times",
"io-extras",
"io-lifetimes",
"ipnet",
"maybe-owned",
"rustix",
"winapi-util",
"windows-sys 0.36.1",
"winx",
]
[[package]]
name = "cap-rand"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d14b9606aa9550d34651bc481443203bc014237bdb992d201d2afa62d2ec6dea"
dependencies = [
"ambient-authority",
"rand 0.8.5",
]
[[package]]
name = "cap-std"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9d6e70b626eceac9d6fc790fe2d72cc3f2f7bc3c35f467690c54a526b0f56db"
dependencies = [
"cap-primitives",
"io-extras",
"io-lifetimes",
"ipnet",
"rustix",
]
[[package]]
name = "cap-time-ext"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a0524f7c4cff2ea547ae2b652bf7a348fd3e48f76556dc928d8b45ab2f1d50"
dependencies = [
"cap-primitives",
"once_cell",
"rustix",
"winx",
]
[[package]]
name = "cart_manager"
version = "0.1.0"
@ -756,6 +836,15 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cpp_demangle"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "cpufeatures"
version = "0.2.5"
@ -765,6 +854,119 @@ dependencies = [
"libc",
]
[[package]]
name = "cranelift-bforest"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c200df7d943cd2b8cb3a67f6a56781c63849f122d74deff24d1767c3918b0bdc"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f365623f4c3d576f47f11868568d0c90e18ac169497a9ed73c433fe2d3f9f2fb"
dependencies = [
"arrayvec",
"bumpalo",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-egraph",
"cranelift-entity",
"cranelift-isle",
"gimli",
"log",
"regalloc2",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-codegen-meta"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cbaf79f8ae63bd86dc40a04417a7cc1691a217f6db204438026c164679b4694"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "587db55845c943d8211e9c7198a977fa6686b44f18df15f31cec9a12fcf5dda8"
[[package]]
name = "cranelift-egraph"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6dccc0b16b7b8c1278162e436beebb35f3d321743b639d2b578138d630f43e"
dependencies = [
"cranelift-entity",
"fxhash",
"hashbrown 0.12.3",
"indexmap",
"log",
"smallvec",
]
[[package]]
name = "cranelift-entity"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b062935d2c6dba87387d2ac163eb9c54967ed6143c3136fffaba8acb5eaa9e"
dependencies = [
"serde",
]
[[package]]
name = "cranelift-frontend"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "476ea81fe736b858d2d2c53b9d9fd28082589f57ebe4e1654a68af7359800a0c"
dependencies = [
"cranelift-codegen",
"log",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-isle"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c50a465703c15d3d913f6b0db8320c4e92c940f0f0cad874c7fcf5aecc066c0"
[[package]]
name = "cranelift-native"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d9e0d1382584b8d454ec12c86fd562b64ccd454c1199846c1b7d158db9ed38"
dependencies = [
"cranelift-codegen",
"libc",
"target-lexicon",
]
[[package]]
name = "cranelift-wasm"
version = "0.90.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f54959195c47437544a1a4d2602381949a12918e0179bcc82d909cc34cf08dd"
dependencies = [
"cranelift-codegen",
"cranelift-entity",
"cranelift-frontend",
"itertools",
"log",
"smallvec",
"wasmparser",
"wasmtime-types",
]
[[package]]
name = "crc"
version = "3.0.0"
@ -1153,6 +1355,27 @@ dependencies = [
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "event-listener"
version = "2.5.3"
@ -1191,6 +1414,12 @@ dependencies = [
"uuid 0.8.2",
]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fastrand"
version = "1.8.0"
@ -1340,6 +1569,17 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs-set-times"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a267b6a9304912e018610d53fe07115d8b530b160e85db4d2d3a59f3ddde1aec"
dependencies = [
"io-lifetimes",
"rustix",
"windows-sys 0.36.1",
]
[[package]]
name = "fs_manager"
version = "0.1.0"
@ -1489,6 +1729,15 @@ dependencies = [
"slab",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "generic-array"
version = "0.14.6"
@ -1512,6 +1761,17 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"fallible-iterator",
"indexmap",
"stable_deref_trait",
]
[[package]]
name = "git2"
version = "0.14.4"
@ -1671,6 +1931,15 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
@ -1890,6 +2159,26 @@ dependencies = [
"unic-langid",
]
[[package]]
name = "io-extras"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5d8c2ab5becd8720e30fd25f8fa5500d8dc3fceadd8378f05859bd7b46fc49"
dependencies = [
"io-lifetimes",
"windows-sys 0.36.1",
]
[[package]]
name = "io-lifetimes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074"
dependencies = [
"libc",
"windows-sys 0.42.0",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -1911,6 +2200,18 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f84f1612606f3753f205a4e9a2efd6fe5b4c573a6269b2cc6c3003d44a0d127"
[[package]]
name = "is-terminal"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d508111813f9af3afd2f92758f77e4ed2cc9371b642112c6a48d22eb73105c5"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys 0.36.1",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -2003,6 +2304,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
version = "0.2.137"
@ -2057,6 +2364,12 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
[[package]]
name = "local-channel"
version = "0.1.3"
@ -2104,6 +2417,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]]
name = "matchers"
version = "0.1.0"
@ -2119,6 +2441,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "maybe-owned"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4"
[[package]]
name = "md-5"
version = "0.10.5"
@ -2365,10 +2693,22 @@ version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
]
[[package]]
name = "object"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"crc32fast",
"hashbrown 0.12.3",
"indexmap",
"memchr",
]
[[package]]
name = "once_cell"
version = "1.16.0"
@ -2639,6 +2979,44 @@ dependencies = [
"thiserror",
]
[[package]]
name = "payment_adapter"
version = "0.1.0"
dependencies = [
"config",
"model",
"wasmtime-api",
"wasmtime-wasi",
]
[[package]]
name = "payment_manager"
version = "0.1.0"
dependencies = [
"channels",
"chrono",
"config",
"db-utils",
"fake",
"gumdrop",
"model",
"opentelemetry 0.17.0",
"opentelemetry-jaeger",
"rumqttc",
"serde",
"sqlx",
"sqlx-core",
"tarpc",
"testx",
"thiserror",
"tokio",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
"uuid 1.2.2",
"wasmtime",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
@ -2792,6 +3170,15 @@ dependencies = [
"trackable 0.2.24",
]
[[package]]
name = "psm"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
dependencies = [
"cc",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
@ -3038,6 +3425,18 @@ dependencies = [
"thiserror",
]
[[package]]
name = "regalloc2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
dependencies = [
"fxhash",
"log",
"slice-group-by",
"smallvec",
]
[[package]]
name = "regex"
version = "1.7.0"
@ -3206,6 +3605,12 @@ dependencies = [
"rust_decimal",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc-hash"
version = "1.1.0"
@ -3230,6 +3635,22 @@ dependencies = [
"semver 1.0.14",
]
[[package]]
name = "rustix"
version = "0.35.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"itoa",
"libc",
"linux-raw-sys",
"once_cell",
"windows-sys 0.42.0",
]
[[package]]
name = "rustls"
version = "0.20.7"
@ -3546,6 +3967,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shellexpand"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
dependencies = [
"dirs",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@ -3579,6 +4009,12 @@ dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "slice-group-by"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
[[package]]
name = "slog"
version = "2.7.0"
@ -3748,6 +4184,12 @@ dependencies = [
"tokio-rustls",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -3840,6 +4282,28 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "system-interface"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92adbaf536f5aff6986e1e62ba36cee72b1718c5153eee08b9e728ddde3f6029"
dependencies = [
"atty",
"bitflags",
"cap-fs-ext",
"cap-std",
"io-lifetimes",
"rustix",
"windows-sys 0.36.1",
"winx",
]
[[package]]
name = "target-lexicon"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
[[package]]
name = "tarpc"
version = "0.31.0"
@ -4416,9 +4880,9 @@ dependencies = [
[[package]]
name = "validator"
version = "0.15.0"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07b0a1390e01c0fc35ebb26b28ced33c9a3808f7f9fbe94d3cc01e233bfeed5"
checksum = "32ad5bf234c7d3ad1042e5252b7eddb2c4669ee23f32c7dd0e9b7705f07ef591"
dependencies = [
"idna 0.2.3",
"lazy_static",
@ -4475,6 +4939,49 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi-cap-std-sync"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe15d7e9ee5bb76cb64b9c29ff00c62642e8552e7f2a8b4758897b0a89a582d"
dependencies = [
"anyhow",
"async-trait",
"cap-fs-ext",
"cap-rand",
"cap-std",
"cap-time-ext",
"fs-set-times",
"io-extras",
"io-lifetimes",
"is-terminal",
"once_cell",
"rustix",
"system-interface",
"tracing",
"wasi-common",
"windows-sys 0.36.1",
]
[[package]]
name = "wasi-common"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e0ef82a2154554def1a220afd48f95cb0f22be343b16930e8957113bd3d967"
dependencies = [
"anyhow",
"bitflags",
"cap-rand",
"cap-std",
"io-extras",
"rustix",
"thiserror",
"tracing",
"wasmtime",
"wiggle",
"windows-sys 0.36.1",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
@ -4543,6 +5050,199 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wasmparser"
version = "0.93.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5a4460aa3e271fa180b6a5d003e728f3963fb30e3ba0fa7c9634caa06049328"
dependencies = [
"indexmap",
]
[[package]]
name = "wasmtime"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ad9bd12d0823195f6c833f340d8d1df39e2bbf40f5767416560ca7476b97e47"
dependencies = [
"anyhow",
"bincode",
"cfg-if 1.0.0",
"indexmap",
"libc",
"log",
"object",
"once_cell",
"paste",
"psm",
"rayon",
"serde",
"target-lexicon",
"wasmparser",
"wasmtime-cranelift",
"wasmtime-environ",
"wasmtime-jit",
"wasmtime-runtime",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-api"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6db9127057c8be35bf5e4dd3d124b99ffe65db4b5631e701a115e3fb4d92590"
[[package]]
name = "wasmtime-asm-macros"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b6694b753be856b36d47744cdf2bd525bac53d0de5981132d5430bb62c496e4"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "wasmtime-cranelift"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c55d30708ebc24b6fa2a247807821642967487388845c7fc5320fef1010abe8"
dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-entity",
"cranelift-frontend",
"cranelift-native",
"cranelift-wasm",
"gimli",
"log",
"object",
"target-lexicon",
"thiserror",
"wasmparser",
"wasmtime-environ",
]
[[package]]
name = "wasmtime-environ"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01be016d65ec9200a2d4efbc2ca983bbb7264332e49c11179aaf7587e57d854d"
dependencies = [
"anyhow",
"cranelift-entity",
"gimli",
"indexmap",
"log",
"object",
"serde",
"target-lexicon",
"thiserror",
"wasmparser",
"wasmtime-types",
]
[[package]]
name = "wasmtime-jit"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d36042d7962fa1b2a6bfb96d3b33e2283138e7396bc29b2c6970f2a1e80a0ed"
dependencies = [
"addr2line",
"anyhow",
"bincode",
"cfg-if 1.0.0",
"cpp_demangle",
"gimli",
"log",
"object",
"rustc-demangle",
"serde",
"target-lexicon",
"thiserror",
"wasmtime-environ",
"wasmtime-jit-icache-coherence",
"wasmtime-runtime",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-jit-debug"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad4511b8abbdbaf3e9aaa4044ead8bd31b70e2da5e43e2cb91605f871ca23d56"
dependencies = [
"once_cell",
]
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb7b3e58024d8d395dfc4efbe2a58360a1998565b118b0342b3cf62a4084bde"
dependencies = [
"cfg-if 1.0.0",
"libc",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-runtime"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4034f371135e9e2e81430dda14f6f5a49a222c6557ec4f65301edc093b216d38"
dependencies = [
"anyhow",
"cc",
"cfg-if 1.0.0",
"indexmap",
"libc",
"log",
"mach",
"memoffset 0.6.5",
"paste",
"rand 0.8.5",
"rustix",
"thiserror",
"wasmtime-asm-macros",
"wasmtime-environ",
"wasmtime-jit-debug",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-types"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a770de14a3b5676dfd8a3c06bcab829d9cb58b113911634f3ec3b6960b1d79e3"
dependencies = [
"cranelift-entity",
"serde",
"thiserror",
"wasmparser",
]
[[package]]
name = "wasmtime-wasi"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648d6b4360af358bf2a0688ef7e35d4b413f7185257bf8de6a58f09fb4d7eca1"
dependencies = [
"anyhow",
"wasi-cap-std-sync",
"wasi-common",
"wasmtime",
"wiggle",
]
[[package]]
name = "wast"
version = "35.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68"
dependencies = [
"leb128",
]
[[package]]
name = "web"
version = "0.1.0"
@ -4613,6 +5313,48 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wiggle"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff29f3353b12c949adc6ad6d89edd87f3fa227b1ee1a26f437ae5e9dfe42ba5f"
dependencies = [
"anyhow",
"async-trait",
"bitflags",
"thiserror",
"tracing",
"wasmtime",
"wiggle-macro",
]
[[package]]
name = "wiggle-generate"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03743b2f04849564d6a2cd6ba32861d93f2d46baddad449473ec399d58b78e3"
dependencies = [
"anyhow",
"heck",
"proc-macro2",
"quote",
"shellexpand",
"syn",
"witx",
]
[[package]]
name = "wiggle-macro"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "544319bbf95f2e0fc2c410b2098aff28a885e6cf59d02a67f5647eec1679d4ec"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wiggle-generate",
]
[[package]]
name = "winapi"
version = "0.2.8"
@ -4765,6 +5507,29 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "winx"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b01e010390eb263a4518c8cebf86cb67469d1511c00b749a47b64c39e8054d"
dependencies = [
"bitflags",
"io-lifetimes",
"windows-sys 0.36.1",
]
[[package]]
name = "witx"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b"
dependencies = [
"anyhow",
"log",
"thiserror",
"wast",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"

View File

@ -12,12 +12,13 @@ members = [
# "crates/database_manager",
"crates/email_manager",
"crates/order_manager",
# "crates/payment_manager",
"crates/payment_manager",
"crates/search_manager",
"crates/stock_manager",
"crates/token_manager",
"crates/fs_manager",
"crates/lang_provider",
"crates/payment_adapter",
# artifacts
# "crates/db-seed",
# "crates/api",

View File

@ -10,7 +10,8 @@ emails = []
search = []
stocks = []
orders = []
default = ['accounts', 'carts', 'emails', 'search', 'stocks', 'orders']
payments = []
default = ['accounts', 'carts', 'emails', 'search', 'stocks', 'orders', 'payments']
[dependencies]
bincode = { version = "*" }

View File

@ -11,6 +11,8 @@ pub mod emails;
pub mod mqtt;
#[cfg(feature = "orders")]
pub mod orders;
#[cfg(feature = "payments")]
pub mod payments;
pub mod rpc;
#[cfg(feature = "search")]
pub mod search;

View File

@ -13,6 +13,8 @@ pub enum Error {
CreateOrder,
#[error("Failed to create order item")]
CreateOrderItem,
#[error("Failed to create order address")]
CreateOrderAddress,
}
#[derive(Debug, Copy, Clone)]
@ -55,8 +57,8 @@ impl AsyncClient {
pub mod create_order {
use model::{
AccountId, Order, OrderAddressId, OrderItem, ProductId, Quantity, QuantityUnit,
ShoppingCartId,
AccountId, City, Country, Email, Name, Order, OrderItem, Phone, ProductId, Quantity,
QuantityUnit, ShoppingCartId, Street, Zip,
};
pub use super::Error;
@ -68,13 +70,24 @@ pub mod create_order {
pub quantity_unit: QuantityUnit,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct AddressInput {
pub name: Name,
pub email: Email,
pub street: Street,
pub city: City,
pub country: Country,
pub zip: Zip,
pub phone: Phone,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Input {
pub buyer_id: AccountId,
pub items: Vec<OrderItemInput>,
pub shopping_cart_id: Option<ShoppingCartId>,
pub checkout_notes: Option<String>,
pub delivery_address_id: OrderAddressId,
pub address: AddressInput,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
@ -119,7 +132,7 @@ pub mod mqtt {
use config::SharedAppConfig;
use rumqttc::EventLoop;
use crate::orders::CLIENT_NAME;
use super::CLIENT_NAME;
use crate::AsyncClient;
pub fn create_client(config: SharedAppConfig) -> (AsyncClient, EventLoop) {

View File

@ -0,0 +1,95 @@
// use rumqttc::QoS;
// use crate::AsyncClient;
pub static CLIENT_NAME: &str = "payments";
#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
pub enum Error {
#[error("Something went wrong")]
InternalServerError,
}
#[derive(Debug, Copy, Clone)]
pub enum Topic {
Succeed,
}
impl Topic {
pub fn to_str(self) -> &'static str {
match self {
Topic::Succeed => "payments/succeed",
}
}
}
impl Into<String> for Topic {
fn into(self) -> String {
self.to_str().into()
}
}
impl<'s> PartialEq<&'s str> for Topic {
fn eq(&self, other: &&'s str) -> bool {
self.to_str() == *other
}
}
impl PartialEq<String> for Topic {
fn eq(&self, other: &String) -> bool {
self.to_str() == other.as_str()
}
}
pub mod start_payment {
use super::Error;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Input {}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Details {}
pub type Output = Result<Details, Error>;
}
pub mod rpc {
use config::SharedAppConfig;
use crate::payments::start_payment;
#[tarpc::service]
pub trait Payments {
async fn start_payment(input: start_payment::Input) -> start_payment::Output;
}
pub async fn create_client(config: SharedAppConfig) -> PaymentsClient {
use tarpc::client;
use tarpc::tokio_serde::formats::Bincode;
let l = config.lock();
let addr = l.orders_manager().rpc_addr();
let transport = tarpc::serde_transport::tcp::connect(addr, Bincode::default);
let client = PaymentsClient::new(
client::Config::default(),
transport.await.expect("Failed to connect to server"),
)
.spawn();
client
}
}
pub mod mqtt {
use config::SharedAppConfig;
use rumqttc::EventLoop;
use super::CLIENT_NAME;
use crate::AsyncClient;
pub fn create_client(config: SharedAppConfig) -> (AsyncClient, EventLoop) {
crate::mqtt::create_client(CLIENT_NAME, config.lock().stocks_manager().mqtt_addr())
}
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use parking_lot::Mutex;
@ -42,83 +44,6 @@ impl std::ops::DerefMut for SharedAppConfig {
}
}
#[derive(Serialize, Deserialize, Default)]
pub struct PaymentConfig {
payu_client_id: Option<pay_u::ClientId>,
payu_client_secret: Option<pay_u::ClientSecret>,
/// Create payu account and copy here merchant id
payu_client_merchant_id: Option<pay_u::MerchantPosId>,
currency: Option<String>,
/// Allow customers to pay on site
#[serde(default)]
optional_payment: bool,
}
impl Example for PaymentConfig {
fn example() -> Self {
Self {
payu_client_id: Some(pay_u::ClientId::new(
"Create payu account and copy here client_id",
)),
payu_client_secret: Some(pay_u::ClientSecret::new(
"Create payu account and copy here client_secret",
)),
/// Create payu account and copy here merchant id
payu_client_merchant_id: Some(pay_u::MerchantPosId::from(0)),
/// Allow customers to pay on site
currency: None,
optional_payment: true,
}
}
}
impl PaymentConfig {
pub fn optional_payment(&self) -> bool {
self.optional_payment
}
pub fn payu_client_id(&self) -> pay_u::ClientId {
self.payu_client_id
.as_ref()
.cloned()
.or_else(|| std::env::var("PAYU_CLIENT_ID").ok().map(pay_u::ClientId))
.expect("payment config payu_client_id nor PAYU_CLIENT_ID env was given")
}
pub fn payu_client_secret(&self) -> pay_u::ClientSecret {
self.payu_client_secret
.as_ref()
.cloned()
.or_else(|| {
std::env::var("PAYU_CLIENT_SECRET")
.ok()
.map(pay_u::ClientSecret)
})
.expect("payment config payu_client_secret nor PAYU_CLIENT_SECRET env was given")
}
pub fn payu_client_merchant_id(&self) -> pay_u::MerchantPosId {
self.payu_client_merchant_id
.or_else(|| {
std::env::var("PAYU_CLIENT_MERCHANT_ID")
.ok()
.and_then(|s| s.parse::<i32>().ok())
.map(pay_u::MerchantPosId)
})
.expect(
"payment config payu_client_merchant_id nor PAYU_CLIENT_MERCHANT_ID env was given",
)
}
pub fn currency(&self) -> String {
self.currency
.as_ref()
.cloned()
.or_else(|| std::env::var("CURRENCY").ok())
.unwrap_or_else(|| "PLN".into())
}
}
#[derive(Serialize, Deserialize, Default)]
pub struct WebConfig {
/// Host name
@ -584,6 +509,121 @@ impl OrderConfig {
}
}
#[derive(Serialize, Deserialize, Default)]
pub struct PaymentProviderConfig {
pub client_id: Option<String>,
pub client_secret: Option<String>,
pub merchant_id: Option<String>,
#[serde(flatten)]
pub custom: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Default)]
pub struct PaymentConfig {
pub rpc_port: u16,
pub rpc_bind: String,
pub mqtt_port: u16,
pub mqtt_bind: String,
pub adapters_path: Option<PathBuf>,
currency: Option<String>,
/// Allow customers to pay on site
#[serde(default)]
optional_payment: bool,
#[serde(flatten)]
providers: HashMap<String, PaymentProviderConfig>,
}
impl Example for PaymentConfig {
fn example() -> Self {
Self {
rpc_port: 19335,
rpc_bind: "0.0.0.0".into(),
mqtt_port: 1888,
mqtt_bind: "0.0.0.0".into(),
adapters_path: Some(Path::new("./adapters").to_path_buf()),
currency: None,
/// Allow customers to pay on site
optional_payment: true,
providers: {
let mut h = HashMap::with_capacity(2);
h.insert(
"pay_u".into(),
PaymentProviderConfig {
client_id: Some("Create payu account and copy here client_id".into()),
client_secret: Some(
"Create payu account and copy here client_secret".into(),
),
merchant_id: Some("Create payu account and copy here merchant id".into()),
custom: {
let mut h = HashMap::with_capacity(2);
h.insert("example1".into(), "custom value1".into());
h.insert("example2".into(), "custom value2".into());
h
},
},
);
h
},
}
}
}
impl PaymentConfig {
pub fn rpc_addr(&self) -> (&str, u16) {
(&self.rpc_bind, self.rpc_port)
}
pub fn mqtt_addr(&self) -> (&str, u16) {
(&self.mqtt_bind, self.mqtt_port)
}
pub fn optional_payment(&self) -> bool {
self.optional_payment
}
//
// pub fn payu_client_id(&self) -> pay_u::ClientId {
// self.payu_client_id
// .as_ref()
// .cloned()
// .or_else(||
// std::env::var("PAYU_CLIENT_ID").ok().map(pay_u::ClientId))
// .expect("payment config payu_client_id nor PAYU_CLIENT_ID env was
// given") }
//
// pub fn payu_client_secret(&self) -> pay_u::ClientSecret {
// self.payu_client_secret
// .as_ref()
// .cloned()
// .or_else(|| {
// std::env::var("PAYU_CLIENT_SECRET")
// .ok()
// .map(pay_u::ClientSecret)
// })
// .expect("payment config payu_client_secret nor PAYU_CLIENT_SECRET env
// was given") }
//
// pub fn payu_client_merchant_id(&self) -> pay_u::MerchantPosId {
// self.payu_client_merchant_id
// .or_else(|| {
// std::env::var("PAYU_CLIENT_MERCHANT_ID")
// .ok()
// .and_then(|s| s.parse::<i32>().ok())
// .map(pay_u::MerchantPosId)
// })
// .expect(
// "payment config payu_client_merchant_id nor
// PAYU_CLIENT_MERCHANT_ID env was given", )
// }
pub fn currency(&self) -> String {
self.currency
.as_ref()
.cloned()
.or_else(|| std::env::var("CURRENCY").ok())
.unwrap_or_else(|| "PLN".into())
}
}
#[derive(Serialize, Deserialize)]
pub struct AppConfig {
#[serde(default)]

View File

@ -7,6 +7,15 @@ edition = "2021"
db = ["sqlx", "sqlx-core"]
dummy = ["fake", "rand"]
accounts = []
carts = []
emails = []
search = []
stocks = []
orders = []
payments = []
default = ['accounts', 'carts', 'emails', 'search', 'stocks', 'orders', 'payments']
[dependencies]
argon2 = { version = "0.4", features = ["parallel", "password-hash"] }
chrono = { version = "0.4", features = ["serde"] }
@ -21,4 +30,4 @@ sqlx-core = { version = "0.6.2", features = [], optional = true }
thiserror = { version = "1.0.31" }
tracing = { version = "0.1.34" }
uuid = { version = "1.2.1", features = ["serde"] }
validator = { version = "0.15.0" }
validator = { version = "0.16.0" }

View File

@ -35,7 +35,7 @@ CREATE TABLE orders
CREATE TABLE order_addresses
(
id serial NOT NULL PRIMARY KEY,
name text NOT NULL,
"name" text NOT NULL,
email text NOT NULL,
street text NOT NULL,
city text NOT NULL,

View File

@ -4,7 +4,7 @@ use config::SharedAppConfig;
use db_utils::{begin_t, dbm_run, PgT};
use model::OrderStatus;
use crate::db::{CreateOrder, CreateOrderItem, Database};
use crate::db::{CreateAddress, CreateOrder, CreateOrderItem, Database};
pub async fn create_order(
input: create_order::Input,
@ -36,11 +36,22 @@ pub async fn inner_create_order(
input: create_order::Input,
t: &mut PgT<'_>,
) -> create_order::Output {
let dbm = CreateAddress {
name: input.address.name,
email: input.address.email,
street: input.address.street,
city: input.address.city,
country: input.address.country,
zip: input.address.zip,
phone: input.address.phone,
};
let address = dbm_run!(dbm, &mut *t, Error::CreateOrderAddress);
let dbm = CreateOrder {
buyer_id: input.buyer_id,
shopping_cart_id: input.shopping_cart_id,
checkout_notes: input.checkout_notes,
delivery_address_id: input.delivery_address_id,
delivery_address_id: address.id,
};
let order = dbm_run!(dbm, &mut *t, Error::CreateOrder);
@ -61,7 +72,7 @@ pub async fn inner_create_order(
Ok(create_order::Details { order, order_items })
}
pub fn change(current: OrderStatus, next: OrderStatus) -> Option<OrderStatus> {
pub fn _change(current: OrderStatus, next: OrderStatus) -> Option<OrderStatus> {
match (current, next) {
// paying
(OrderStatus::Confirmed, OrderStatus::Payed) => Some(OrderStatus::Payed),

View File

@ -17,6 +17,7 @@ pub struct CreateOrder {
}
impl CreateOrder {
#[tracing::instrument]
pub async fn run(self, t: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> Result<Order> {
sqlx::query_as(
r#"

View File

@ -0,0 +1,156 @@
use db_utils::PgT;
use model::{
City, Country, Email, Name, OrderAddress, OrderAddressId, OrderId, Phone, Street, Zip,
};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Failed to load address for order {0:?}")]
AddressForOrder(OrderId),
#[error("Failed to create address for order")]
Create,
#[error("Failed to update address {address_id:?} for order {order_id:?}")]
Update {
order_id: OrderId,
address_id: OrderAddressId,
},
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct AddressForOrder {
pub order_id: OrderId,
}
impl AddressForOrder {
#[tracing::instrument]
pub async fn run(self, t: &mut PgT<'_>) -> Result<OrderAddress> {
sqlx::query_as(
r#"
SELECT a.id,
a.name,
a.email,
a.street,
a.city,
a.country,
a.zip,
a.phone
FROM order_addresses a
IINER JOIN orders o ON orders.address_id = id
WHERE o.id = $1
LIMIT 1
"#,
)
.bind(self.order_id)
.fetch_one(t)
.await
.map_err(|e| {
tracing::error!("{}", e);
Error::AddressForOrder(self.order_id)
})
}
}
#[derive(Debug)]
pub struct CreateAddress {
pub name: Name,
pub email: Email,
pub street: Street,
pub city: City,
pub country: Country,
pub zip: Zip,
pub phone: Phone,
}
impl CreateAddress {
#[tracing::instrument]
pub async fn run(self, t: &mut PgT<'_>) -> Result<OrderAddress> {
sqlx::query_as(
r#"
INSERT INTO order_addresses (
name,
email,
street,
city,
country,
zip,
phone
)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id,
name,
email,
street,
city,
country,
zip,
phone
"#,
)
.bind(self.name)
.bind(self.email)
.bind(self.street)
.bind(self.city)
.bind(self.country)
.bind(self.zip)
.bind(self.phone)
.fetch_one(t)
.await
.map_err(|e| {
tracing::error!("{}", e);
Error::Create
})
}
}
#[derive(Debug)]
pub struct UpdateAddress {
pub order_id: OrderId,
pub address_id: OrderAddressId,
pub name: Name,
pub email: Email,
pub street: Street,
pub city: City,
pub country: Country,
pub zip: Zip,
pub phone: Phone,
}
impl UpdateAddress {
#[tracing::instrument]
pub async fn run(self, t: &mut PgT<'_>) -> Result<OrderAddress> {
sqlx::query_as(
r#"
UPDATE order_addresses
SET name = $2, email = $3, street = $4, city = $5, country = $6, zip = $7, phone = $8
WHERE id = $1
RETURNING id,
name,
email,
street,
city,
country,
zip,
phone
"#,
)
.bind(self.address_id)
.bind(self.name)
.bind(self.email)
.bind(self.street)
.bind(self.city)
.bind(self.country)
.bind(self.zip)
.bind(self.phone)
.fetch_one(t)
.await
.map_err(|e| {
tracing::error!("{}", e);
Error::Update {
order_id: self.order_id,
address_id: self.address_id,
}
})
}
}

View File

@ -17,6 +17,7 @@ pub struct CreateOrderItem {
}
impl CreateOrderItem {
#[tracing::instrument]
pub async fn run(self, t: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> Result<OrderItem> {
sqlx::query_as(
r#"

View File

@ -4,6 +4,7 @@ mod actions;
mod db;
mod mqtt;
mod rpc;
mod context;
pub struct Opts {}

View File

@ -0,0 +1,10 @@
[package]
name = "payment_adapter"
version = "0.1.0"
edition = "2021"
[dependencies]
wasmtime-wasi = { version = "3.0.0" }
wasmtime-api = { version = "0.4.0" }
config = { path = "../config" }
model = { path = "../model" }

View File

@ -0,0 +1,48 @@
use std::collections::HashMap;
pub use config::PaymentProviderConfig;
use model::{Price, ProductId, Quantity, QuantityUnit};
#[derive(Debug)]
pub struct Buyer {
/// Required customer e-mail
pub email: String,
/// Required customer phone number
pub phone: String,
/// Required customer first name
pub first_name: String,
/// Required customer last name
pub last_name: String,
/// Required customer language
pub language: String,
}
#[derive(Debug)]
pub struct Product {
pub id: ProductId,
pub name: String,
pub unit_price: Price,
pub quantity_unit: QuantityUnit,
pub quantity: Quantity,
}
pub struct CreatePayment {
// pub client: PayUClient,
pub buyer: Buyer,
pub customer_ip: String,
pub currency: String,
pub description: String,
pub cart_products: Vec<Product>,
pub items: HashMap<ProductId, (Quantity, QuantityUnit)>,
pub order_ext_id: String,
pub notify_uri: String,
pub continue_uri: String,
}
pub trait PaymentAdapter {
fn name() -> &'static str;
fn init(&mut self, config: &PaymentProviderConfig);
fn create_payment(&self, msg: CreatePayment);
}

View File

@ -3,22 +3,31 @@ name = "payment_manager"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "payment-manager"
path = "./src/main.rs"
[dependencies]
actix = { version = "0.13", features = [] }
actix-rt = { version = "2.7", features = [] }
channels = { path = "../channels" }
chrono = { version = "0.4", features = ["serde"] }
config = { path = "../config" }
database_manager = { path = "../database_manager" }
derive_more = { version = "0.99", features = [] }
db-utils = { path = "../db-utils" }
model = { path = "../model", features = ["db"] }
parking_lot = { version = "0.12", features = [] }
pay_u = { version = '0.1', features = ["single-client"] }
pretty_env_logger = { version = "0.4", features = [] }
opentelemetry = { version = "0.17.0" }
opentelemetry-jaeger = { version = "0.17.0" }
rumqttc = { version = "*" }
serde = { version = "1.0", features = ["derive"] }
serde = { version = "1.0.137", features = ["derive"] }
sqlx = { version = "0.6.2", features = ["migrate", "runtime-actix-rustls", "all-types", "postgres"] }
sqlx-core = { version = "0.6.2", features = [] }
tarpc = { version = "0.31.0", features = ["tokio1", "serde-transport-bincode", "serde-transport", "serde", "serde-transport-json", "tcp"] }
thiserror = { version = "1.0.31" }
tracing = { version = "0.1.34" }
uuid = { version = "0.8", features = ["serde"] }
tokio = { version = "1.21.2", features = ['full'] }
tracing = { version = "0.1.6" }
tracing-opentelemetry = { version = "0.17.4" }
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
uuid = { version = "1.2.1", features = ["serde"] }
wasmtime = { version = "3.0.0", default-features = false, features = ['cranelift', 'parallel-compilation', 'pooling-allocator'] }
gumdrop = { version = "0.8.1", features = [] }
[dev-dependencies]
fake = { version = "2.5.0" }

View File

@ -0,0 +1,2 @@
mod pay_u_adapter;
mod t_pay_adapter;

View File

@ -1,68 +1,10 @@
mod pay_u_adapter;
mod t_pay_adapter;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use actix::Addr;
use config::SharedAppConfig;
use database_manager::{query_db, Database};
use model::{
AccountId, OrderId, OrderStatus, PaymentMethod, Price, ProductId, Quantity, QuantityUnit,
};
use parking_lot::Mutex;
#[macro_export]
macro_rules! pay_async_handler {
($msg: ty, $async: ident, $res: ty) => {
impl actix::Handler<$msg> for PaymentManager {
type Result = actix::ResponseActFuture<Self, Result<$res>>;
fn handle(&mut self, msg: $msg, _ctx: &mut Self::Context) -> Self::Result {
use actix::WrapFuture;
let client = self.client.clone();
let db = self.db.clone();
let config = self.config.clone();
Box::pin(async { $async(msg, client, db, config).await }.into_actor(self))
}
}
};
}
#[macro_export]
macro_rules! query_pay {
($manager: expr, $msg: expr, default $fail: expr) => {
match $manager.send($msg).await {
Ok(Ok(r)) => r,
Ok(Err(e)) => {
tracing::error!("Payment {e}");
$fail
}
Err(e) => {
tracing::error!("Payment {e:?}");
$fail
}
}
};
($manager: expr, $msg: expr, $fail: expr) => {
$crate::query_pay!($manager, $msg, $fail, $fail)
};
($manager: expr, $msg: expr, $db_fail: expr, $act_fail: expr) => {
match $manager.send($msg).await {
Ok(Ok(r)) => r,
Ok(Err(e)) => {
tracing::error!("Payment {e}");
return Err($db_fail);
}
Err(e) => {
tracing::error!("Payment {e:?}");
return Err($act_fail);
}
}
};
}
pub type PayUClient = Arc<Mutex<pay_u::Client>>;
@ -84,101 +26,62 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone)]
pub struct PaymentManager {
client: PayUClient,
db: Addr<Database>,
config: SharedAppConfig,
}
impl PaymentManager {
pub async fn build(config: SharedAppConfig, db: Addr<Database>) -> Self {
let mut client = {
let l = config.lock();
let p = l.payment();
pay_u::Client::new(
p.payu_client_id(),
p.payu_client_secret(),
p.payu_client_merchant_id(),
)
};
client.authorize().await.unwrap_or_else(|e| {
tracing::error!("{e}");
dbg!(e);
std::process::exit(1);
});
Self {
client: Arc::new(Mutex::new(client)),
db,
config,
}
}
}
impl actix::Actor for PaymentManager {
type Context = actix::Context<Self>;
}
// impl PaymentManager {
// pub async fn build(config: SharedAppConfig, db: Addr<Database>) -> Self {
// let mut client = {
// let l = config.lock();
// let p = l.payment();
// pay_u::Client::new(
// p.payu_client_id(),
// p.payu_client_secret(),
// p.payu_client_merchant_id(),
// )
// };
// client.authorize().await.unwrap_or_else(|e| {
// tracing::error!("{e}");
// dbg!(e);
// std::process::exit(1);
// });
// Self {
// client: Arc::new(Mutex::new(client)),
// db,
// config,
// }
// }
// }
//
// impl actix::Actor for PaymentManager {
// type Context = actix::Context<Self>;
// }
pub struct PaymentResult {
pub redirect_uri: String,
pub payu_order_id: String,
}
#[derive(Debug)]
pub struct Buyer {
/// Required customer e-mail
pub email: String,
/// Required customer phone number
pub phone: String,
/// Required customer first name
pub first_name: String,
/// Required customer last name
pub last_name: String,
/// Required customer language
pub language: String,
}
impl From<Buyer> for pay_u::Buyer {
fn from(b: Buyer) -> Self {
pay_u::Buyer::new(b.email, b.phone, b.first_name, b.last_name, b.language)
}
}
#[derive(Debug)]
pub struct Product {
pub id: ProductId,
pub name: String,
pub unit_price: Price,
pub quantity_unit: QuantityUnit,
pub quantity: Quantity,
}
impl From<Product> for pay_u::Product {
fn from(p: Product) -> Self {
pay_u::Product::new(p.name, **p.unit_price, **p.quantity as u32)
}
}
pub struct CreatePaymentResult {
pub order: model::Order,
pub items: Vec<model::OrderItem>,
pub redirect_uri: String,
}
#[derive(Debug, actix::Message)]
#[rtype(result = "Result<CreatePaymentResult>")]
#[derive(Debug)]
pub struct RequestPayment {
pub currency: String,
pub buyer: Buyer,
pub buyer: model::Buyer,
pub customer_ip: String,
pub buyer_id: AccountId,
pub payment_method: PaymentMethod,
pub db_order_id: OrderId,
}
pay_async_handler!(RequestPayment, request_payment, CreatePaymentResult);
pub(crate) async fn request_payment(
pub async fn request_payment(
msg: RequestPayment,
client: PayUClient,
db: Addr<Database>,
// db: Addr<Database>,
config: SharedAppConfig,
) -> Result<CreatePaymentResult> {
let db_order: model::Order = query_db!(
@ -236,7 +139,7 @@ pub(crate) async fn request_payment(
let redirect_uri = match msg.payment_method {
PaymentMethod::PayU => {
let (redirect_uri, ext_order_id) = pay_u_adapter::CreatePayment {
let (redirect_uri, ext_order_id) = crate::pay_u_adapter::CreatePayment {
client,
buyer: msg.buyer,
customer_ip: msg.customer_ip,
@ -283,18 +186,14 @@ pub(crate) async fn request_payment(
#[serde(transparent)]
pub struct PaymentNotification(pay_u::notify::StatusUpdate);
#[derive(Debug, actix::Message)]
#[rtype(result = "Result<()>")]
pub struct UpdatePayment {
pub notification: PaymentNotification,
}
pay_async_handler!(UpdatePayment, update_payment, ());
pub(crate) async fn update_payment(
pub async fn payment_notification(
msg: UpdatePayment,
_client: PayUClient,
db: Addr<Database>,
// db: Addr<Database>,
_config: SharedAppConfig,
) -> Result<()> {
let status = msg.notification.0.status();
@ -308,12 +207,12 @@ pub(crate) async fn update_payment(
pay_u::PaymentStatus::Completed => OrderStatus::Payed,
pay_u::PaymentStatus::Canceled => OrderStatus::Cancelled,
};
let _ = db
.send(database_manager::UpdateOrderByExt {
status,
order_ext_id,
})
.await;
// let _ = db
// .send(database_manager::UpdateOrderByExt {
// status,
// order_ext_id,
// })
// .await;
Ok(())
}
@ -327,11 +226,11 @@ mod tests {
impl config::UpdateConfig for NoOpts {}
#[actix::test]
#[tokio::test]
async fn create() {
testx::db!(config, db);
let db = db.start();
let _manager = PaymentManager::build(config, db).await;
// testx::db!(config, db);
// let db = db.start();
//
// let _manager = PaymentManager::build(config, db).await;
}
}

View File

View File

View File

@ -0,0 +1,53 @@
use std::fs::read_dir;
use std::path::PathBuf;
use config::{AppConfig, UpdateConfig};
// mod actions;
// mod context;
// mod db;
// mod mqtt;
// pub mod pay_u_adapter;
// mod rpc;
// pub mod t_pay_adapter;
#[derive(gumdrop::Options)]
pub struct Opts {
pub adapters_path: Option<PathBuf>,
}
impl UpdateConfig for Opts {
fn update_config(&self, config: &mut AppConfig) {
if let Some(path) = self.adapters_path.clone() {
config.payment_mut().adapters_path = Some(path);
}
}
}
#[tokio::main]
async fn main() {
let opts: Opts = gumdrop::parse_args_default_or_exit();
let config = config::default_load(&opts);
let engine = wasmtime::Engine::default();
{
let adapters_path = config.lock().payment().adapters_path.clone();
let adapters = adapters_path.unwrap_or_else(|| panic!("No payment adapters path provided"));
let dir = read_dir(&adapters).unwrap_or_else(|e| {
panic!(
"Failed to load payment adapters at path {:?}. {}",
adapters, e
)
});
for file in dir.filter_map(|r| r.map(|r| r.path()).ok()) {
wasmtime::Module::from_file(&engine, file).unwrap();
}
}
// let db = db::Database::build(config.clone()).await;
// let mqtt_client = mqtt::start(config.clone(), db.clone()).await;
// rpc::start(config, db, mqtt_client).await;
}

View File

View File

@ -2,7 +2,47 @@ use std::collections::HashMap;
use model::*;
use crate::{Buyer, Error, PayUClient, Result};
// use crate::{Buyer, Error, PayUClient, Result};
#[derive(Debug, thiserror::Error)]
pub enum Error {}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct Buyer {
/// Required customer e-mail
pub email: String,
/// Required customer phone number
pub phone: String,
/// Required customer first name
pub first_name: String,
/// Required customer last name
pub last_name: String,
/// Required customer language
pub language: String,
}
impl From<Buyer> for pay_u::Buyer {
fn from(b: Buyer) -> Self {
pay_u::Buyer::new(b.email, b.phone, b.first_name, b.last_name, b.language)
}
}
#[derive(Debug)]
pub struct Product {
pub id: ProductId,
pub name: String,
pub unit_price: Price,
pub quantity_unit: QuantityUnit,
pub quantity: Quantity,
}
impl From<Product> for pay_u::Product {
fn from(p: Product) -> Self {
pay_u::Product::new(p.name, **p.unit_price, **p.quantity as u32)
}
}
pub struct CreatePayment {
pub client: PayUClient,
@ -11,7 +51,7 @@ pub struct CreatePayment {
pub currency: String,
pub description: String,
pub cart_products: Vec<model::Product>,
pub items: HashMap<ProductId, (model::Quantity, QuantityUnit)>,
pub items: HashMap<ProductId, (Quantity, QuantityUnit)>,
pub order_ext_id: String,
pub notify_uri: String,
pub continue_uri: String,

View File