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 node_modules
web/dist web/dist
web/tmp web/tmp
adapters

773
Cargo.lock generated
View File

@ -246,6 +246,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]] [[package]]
name = "adler" name = "adler"
version = "1.0.2" version = "1.0.2"
@ -287,6 +296,12 @@ dependencies = [
"alloc-no-stdlib", "alloc-no-stdlib",
] ]
[[package]]
name = "ambient-authority"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec8ad6edb4840b78c5c3d88de606b22252d552b55f3a4699fbb10fc070ec3049"
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@ -361,7 +376,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi 0.1.19",
"libc", "libc",
"winapi 0.3.9", "winapi 0.3.9",
] ]
@ -576,6 +591,71 @@ dependencies = [
"bytes", "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]] [[package]]
name = "cart_manager" name = "cart_manager"
version = "0.1.0" version = "0.1.0"
@ -756,6 +836,15 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 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]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.5" version = "0.2.5"
@ -765,6 +854,119 @@ dependencies = [
"libc", "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]] [[package]]
name = "crc" name = "crc"
version = "3.0.0" version = "3.0.0"
@ -1153,6 +1355,27 @@ dependencies = [
"termcolor", "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]] [[package]]
name = "event-listener" name = "event-listener"
version = "2.5.3" version = "2.5.3"
@ -1191,6 +1414,12 @@ dependencies = [
"uuid 0.8.2", "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]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.8.0" version = "1.8.0"
@ -1340,6 +1569,17 @@ dependencies = [
"percent-encoding", "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]] [[package]]
name = "fs_manager" name = "fs_manager"
version = "0.1.0" version = "0.1.0"
@ -1489,6 +1729,15 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.6" version = "0.14.6"
@ -1512,6 +1761,17 @@ dependencies = [
"wasm-bindgen", "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]] [[package]]
name = "git2" name = "git2"
version = "0.14.4" version = "0.14.4"
@ -1671,6 +1931,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hex" name = "hex"
version = "0.4.3" version = "0.4.3"
@ -1890,6 +2159,26 @@ dependencies = [
"unic-langid", "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]] [[package]]
name = "iovec" name = "iovec"
version = "0.1.4" version = "0.1.4"
@ -1911,6 +2200,18 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f84f1612606f3753f205a4e9a2efd6fe5b4c573a6269b2cc6c3003d44a0d127" 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]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -2003,6 +2304,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.137" version = "0.2.137"
@ -2057,6 +2364,12 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
[[package]] [[package]]
name = "local-channel" name = "local-channel"
version = "0.1.3" version = "0.1.3"
@ -2104,6 +2417,15 @@ dependencies = [
"winapi 0.3.9", "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]] [[package]]
name = "matchers" name = "matchers"
version = "0.1.0" version = "0.1.0"
@ -2119,6 +2441,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "maybe-owned"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4"
[[package]] [[package]]
name = "md-5" name = "md-5"
version = "0.10.5" version = "0.10.5"
@ -2365,10 +2693,22 @@ version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi 0.1.19",
"libc", "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]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.16.0"
@ -2639,6 +2979,44 @@ dependencies = [
"thiserror", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.2.0" version = "2.2.0"
@ -2792,6 +3170,15 @@ dependencies = [
"trackable 0.2.24", "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]] [[package]]
name = "ptr_meta" name = "ptr_meta"
version = "0.1.4" version = "0.1.4"
@ -3038,6 +3425,18 @@ dependencies = [
"thiserror", "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]] [[package]]
name = "regex" name = "regex"
version = "1.7.0" version = "1.7.0"
@ -3206,6 +3605,12 @@ dependencies = [
"rust_decimal", "rust_decimal",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "1.1.0" version = "1.1.0"
@ -3230,6 +3635,22 @@ dependencies = [
"semver 1.0.14", "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]] [[package]]
name = "rustls" name = "rustls"
version = "0.20.7" version = "0.20.7"
@ -3546,6 +3967,15 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "shellexpand"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
dependencies = [
"dirs",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.0" version = "1.4.0"
@ -3579,6 +4009,12 @@ dependencies = [
"autocfg 1.1.0", "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]] [[package]]
name = "slog" name = "slog"
version = "2.7.0" version = "2.7.0"
@ -3748,6 +4184,12 @@ dependencies = [
"tokio-rustls", "tokio-rustls",
] ]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "static_assertions" name = "static_assertions"
version = "1.1.0" version = "1.1.0"
@ -3840,6 +4282,28 @@ dependencies = [
"unicode-ident", "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]] [[package]]
name = "tarpc" name = "tarpc"
version = "0.31.0" version = "0.31.0"
@ -4416,9 +4880,9 @@ dependencies = [
[[package]] [[package]]
name = "validator" name = "validator"
version = "0.15.0" version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07b0a1390e01c0fc35ebb26b28ced33c9a3808f7f9fbe94d3cc01e233bfeed5" checksum = "32ad5bf234c7d3ad1042e5252b7eddb2c4669ee23f32c7dd0e9b7705f07ef591"
dependencies = [ dependencies = [
"idna 0.2.3", "idna 0.2.3",
"lazy_static", "lazy_static",
@ -4475,6 +4939,49 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 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]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.83" version = "0.2.83"
@ -4543,6 +5050,199 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 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]] [[package]]
name = "web" name = "web"
version = "0.1.0" version = "0.1.0"
@ -4613,6 +5313,48 @@ dependencies = [
"web-sys", "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]] [[package]]
name = "winapi" name = "winapi"
version = "0.2.8" version = "0.2.8"
@ -4765,6 +5507,29 @@ dependencies = [
"winapi 0.3.9", "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]] [[package]]
name = "ws2_32-sys" name = "ws2_32-sys"
version = "0.2.1" version = "0.2.1"

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,15 @@ edition = "2021"
db = ["sqlx", "sqlx-core"] db = ["sqlx", "sqlx-core"]
dummy = ["fake", "rand"] dummy = ["fake", "rand"]
accounts = []
carts = []
emails = []
search = []
stocks = []
orders = []
payments = []
default = ['accounts', 'carts', 'emails', 'search', 'stocks', 'orders', 'payments']
[dependencies] [dependencies]
argon2 = { version = "0.4", features = ["parallel", "password-hash"] } argon2 = { version = "0.4", features = ["parallel", "password-hash"] }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
@ -21,4 +30,4 @@ sqlx-core = { version = "0.6.2", features = [], optional = true }
thiserror = { version = "1.0.31" } thiserror = { version = "1.0.31" }
tracing = { version = "0.1.34" } tracing = { version = "0.1.34" }
uuid = { version = "1.2.1", features = ["serde"] } 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 CREATE TABLE order_addresses
( (
id serial NOT NULL PRIMARY KEY, id serial NOT NULL PRIMARY KEY,
name text NOT NULL, "name" text NOT NULL,
email text NOT NULL, email text NOT NULL,
street text NOT NULL, street text NOT NULL,
city 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 db_utils::{begin_t, dbm_run, PgT};
use model::OrderStatus; use model::OrderStatus;
use crate::db::{CreateOrder, CreateOrderItem, Database}; use crate::db::{CreateAddress, CreateOrder, CreateOrderItem, Database};
pub async fn create_order( pub async fn create_order(
input: create_order::Input, input: create_order::Input,
@ -36,11 +36,22 @@ pub async fn inner_create_order(
input: create_order::Input, input: create_order::Input,
t: &mut PgT<'_>, t: &mut PgT<'_>,
) -> create_order::Output { ) -> 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 { let dbm = CreateOrder {
buyer_id: input.buyer_id, buyer_id: input.buyer_id,
shopping_cart_id: input.shopping_cart_id, shopping_cart_id: input.shopping_cart_id,
checkout_notes: input.checkout_notes, 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); 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 }) 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) { match (current, next) {
// paying // paying
(OrderStatus::Confirmed, OrderStatus::Payed) => Some(OrderStatus::Payed), (OrderStatus::Confirmed, OrderStatus::Payed) => Some(OrderStatus::Payed),

View File

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

View File

@ -4,6 +4,7 @@ mod actions;
mod db; mod db;
mod mqtt; mod mqtt;
mod rpc; mod rpc;
mod context;
pub struct Opts {} 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" version = "0.1.0"
edition = "2021" edition = "2021"
[[bin]]
name = "payment-manager"
path = "./src/main.rs"
[dependencies] [dependencies]
actix = { version = "0.13", features = [] } channels = { path = "../channels" }
actix-rt = { version = "2.7", features = [] }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
config = { path = "../config" } config = { path = "../config" }
database_manager = { path = "../database_manager" } db-utils = { path = "../db-utils" }
derive_more = { version = "0.99", features = [] }
model = { path = "../model", features = ["db"] } model = { path = "../model", features = ["db"] }
parking_lot = { version = "0.12", features = [] } opentelemetry = { version = "0.17.0" }
pay_u = { version = '0.1', features = ["single-client"] } opentelemetry-jaeger = { version = "0.17.0" }
pretty_env_logger = { version = "0.4", features = [] }
rumqttc = { version = "*" } 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" } thiserror = { version = "1.0.31" }
tracing = { version = "0.1.34" } tokio = { version = "1.21.2", features = ['full'] }
uuid = { version = "0.8", features = ["serde"] } 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] [dev-dependencies]
fake = { version = "2.5.0" } 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::collections::HashMap;
use std::sync::Arc; use std::sync::{Arc, Mutex};
use actix::Addr;
use config::SharedAppConfig; use config::SharedAppConfig;
use database_manager::{query_db, Database};
use model::{ use model::{
AccountId, OrderId, OrderStatus, PaymentMethod, Price, ProductId, Quantity, QuantityUnit, 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>>; pub type PayUClient = Arc<Mutex<pay_u::Client>>;
@ -84,101 +26,62 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone)] #[derive(Clone)]
pub struct PaymentManager { pub struct PaymentManager {
client: PayUClient, client: PayUClient,
db: Addr<Database>,
config: SharedAppConfig, config: SharedAppConfig,
} }
impl PaymentManager { // impl PaymentManager {
pub async fn build(config: SharedAppConfig, db: Addr<Database>) -> Self { // pub async fn build(config: SharedAppConfig, db: Addr<Database>) -> Self {
let mut client = { // let mut client = {
let l = config.lock(); // let l = config.lock();
let p = l.payment(); // let p = l.payment();
pay_u::Client::new( // pay_u::Client::new(
p.payu_client_id(), // p.payu_client_id(),
p.payu_client_secret(), // p.payu_client_secret(),
p.payu_client_merchant_id(), // p.payu_client_merchant_id(),
) // )
}; // };
client.authorize().await.unwrap_or_else(|e| { // client.authorize().await.unwrap_or_else(|e| {
tracing::error!("{e}"); // tracing::error!("{e}");
dbg!(e); // dbg!(e);
std::process::exit(1); // std::process::exit(1);
}); // });
Self { // Self {
client: Arc::new(Mutex::new(client)), // client: Arc::new(Mutex::new(client)),
db, // db,
config, // config,
} // }
} // }
} // }
//
impl actix::Actor for PaymentManager { // impl actix::Actor for PaymentManager {
type Context = actix::Context<Self>; // type Context = actix::Context<Self>;
} // }
pub struct PaymentResult { pub struct PaymentResult {
pub redirect_uri: String, pub redirect_uri: String,
pub payu_order_id: 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 struct CreatePaymentResult {
pub order: model::Order, pub order: model::Order,
pub items: Vec<model::OrderItem>, pub items: Vec<model::OrderItem>,
pub redirect_uri: String, pub redirect_uri: String,
} }
#[derive(Debug, actix::Message)] #[derive(Debug)]
#[rtype(result = "Result<CreatePaymentResult>")]
pub struct RequestPayment { pub struct RequestPayment {
pub currency: String, pub currency: String,
pub buyer: Buyer, pub buyer: model::Buyer,
pub customer_ip: String, pub customer_ip: String,
pub buyer_id: AccountId, pub buyer_id: AccountId,
pub payment_method: PaymentMethod, pub payment_method: PaymentMethod,
pub db_order_id: OrderId, pub db_order_id: OrderId,
} }
pay_async_handler!(RequestPayment, request_payment, CreatePaymentResult); pub async fn request_payment(
pub(crate) async fn request_payment(
msg: RequestPayment, msg: RequestPayment,
client: PayUClient, client: PayUClient,
db: Addr<Database>, // db: Addr<Database>,
config: SharedAppConfig, config: SharedAppConfig,
) -> Result<CreatePaymentResult> { ) -> Result<CreatePaymentResult> {
let db_order: model::Order = query_db!( let db_order: model::Order = query_db!(
@ -236,7 +139,7 @@ pub(crate) async fn request_payment(
let redirect_uri = match msg.payment_method { let redirect_uri = match msg.payment_method {
PaymentMethod::PayU => { PaymentMethod::PayU => {
let (redirect_uri, ext_order_id) = pay_u_adapter::CreatePayment { let (redirect_uri, ext_order_id) = crate::pay_u_adapter::CreatePayment {
client, client,
buyer: msg.buyer, buyer: msg.buyer,
customer_ip: msg.customer_ip, customer_ip: msg.customer_ip,
@ -283,18 +186,14 @@ pub(crate) async fn request_payment(
#[serde(transparent)] #[serde(transparent)]
pub struct PaymentNotification(pay_u::notify::StatusUpdate); pub struct PaymentNotification(pay_u::notify::StatusUpdate);
#[derive(Debug, actix::Message)]
#[rtype(result = "Result<()>")]
pub struct UpdatePayment { pub struct UpdatePayment {
pub notification: PaymentNotification, pub notification: PaymentNotification,
} }
pay_async_handler!(UpdatePayment, update_payment, ()); pub async fn payment_notification(
pub(crate) async fn update_payment(
msg: UpdatePayment, msg: UpdatePayment,
_client: PayUClient, _client: PayUClient,
db: Addr<Database>, // db: Addr<Database>,
_config: SharedAppConfig, _config: SharedAppConfig,
) -> Result<()> { ) -> Result<()> {
let status = msg.notification.0.status(); 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::Completed => OrderStatus::Payed,
pay_u::PaymentStatus::Canceled => OrderStatus::Cancelled, pay_u::PaymentStatus::Canceled => OrderStatus::Cancelled,
}; };
let _ = db // let _ = db
.send(database_manager::UpdateOrderByExt { // .send(database_manager::UpdateOrderByExt {
status, // status,
order_ext_id, // order_ext_id,
}) // })
.await; // .await;
Ok(()) Ok(())
} }
@ -327,11 +226,11 @@ mod tests {
impl config::UpdateConfig for NoOpts {} impl config::UpdateConfig for NoOpts {}
#[actix::test] #[tokio::test]
async fn create() { async fn create() {
testx::db!(config, db); // testx::db!(config, db);
let db = db.start(); // let db = db.start();
//
let _manager = PaymentManager::build(config, db).await; // 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 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 struct CreatePayment {
pub client: PayUClient, pub client: PayUClient,
@ -11,7 +51,7 @@ pub struct CreatePayment {
pub currency: String, pub currency: String,
pub description: String, pub description: String,
pub cart_products: Vec<model::Product>, 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 order_ext_id: String,
pub notify_uri: String, pub notify_uri: String,
pub continue_uri: String, pub continue_uri: String,

View File