Add loadable payment adapters

This commit is contained in:
Adrian Woźniak 2022-12-02 16:05:55 +01:00
parent 1d775e3e1a
commit 89c2aff705
20 changed files with 2961 additions and 102 deletions

View File

@ -3,3 +3,5 @@ linker = "clang"
rustflags = [
"-C", "link-arg=-fuse-ld=mold",
]
[build]
rustc-wrapper = "/usr/bin/sccache"

500
Cargo.lock generated
View File

@ -599,7 +599,7 @@ checksum = "0b0e103ce36d217d568903ad27b14ec2238ecb5d65bad2e756a8f3c0d651506e"
dependencies = [
"cap-primitives",
"cap-std",
"io-lifetimes",
"io-lifetimes 0.7.5",
"windows-sys 0.36.1",
]
@ -612,10 +612,10 @@ dependencies = [
"ambient-authority",
"fs-set-times",
"io-extras",
"io-lifetimes",
"io-lifetimes 0.7.5",
"ipnet",
"maybe-owned",
"rustix",
"rustix 0.35.13",
"winapi-util",
"windows-sys 0.36.1",
"winx",
@ -639,9 +639,9 @@ checksum = "c9d6e70b626eceac9d6fc790fe2d72cc3f2f7bc3c35f467690c54a526b0f56db"
dependencies = [
"cap-primitives",
"io-extras",
"io-lifetimes",
"io-lifetimes 0.7.5",
"ipnet",
"rustix",
"rustix 0.35.13",
]
[[package]]
@ -652,7 +652,7 @@ checksum = "c3a0524f7c4cff2ea547ae2b652bf7a348fd3e48f76556dc928d8b45ab2f1d50"
dependencies = [
"cap-primitives",
"once_cell",
"rustix",
"rustix 0.35.13",
"winx",
]
@ -767,7 +767,6 @@ dependencies = [
"cookie",
"parking_lot 0.12.1",
"password-hash",
"pay_u",
"serde",
"serde_json",
"thiserror",
@ -856,18 +855,18 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c200df7d943cd2b8cb3a67f6a56781c63849f122d74deff24d1767c3918b0bdc"
checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f365623f4c3d576f47f11868568d0c90e18ac169497a9ed73c433fe2d3f9f2fb"
checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
dependencies = [
"arrayvec",
"bumpalo",
@ -886,24 +885,24 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cbaf79f8ae63bd86dc40a04417a7cc1691a217f6db204438026c164679b4694"
checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "587db55845c943d8211e9c7198a977fa6686b44f18df15f31cec9a12fcf5dda8"
checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
[[package]]
name = "cranelift-egraph"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6dccc0b16b7b8c1278162e436beebb35f3d321743b639d2b578138d630f43e"
checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
dependencies = [
"cranelift-entity",
"fxhash",
@ -915,18 +914,18 @@ dependencies = [
[[package]]
name = "cranelift-entity"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b062935d2c6dba87387d2ac163eb9c54967ed6143c3136fffaba8acb5eaa9e"
checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
dependencies = [
"serde",
]
[[package]]
name = "cranelift-frontend"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "476ea81fe736b858d2d2c53b9d9fd28082589f57ebe4e1654a68af7359800a0c"
checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
dependencies = [
"cranelift-codegen",
"log",
@ -936,15 +935,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c50a465703c15d3d913f6b0db8320c4e92c940f0f0cad874c7fcf5aecc066c0"
checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
[[package]]
name = "cranelift-native"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d9e0d1382584b8d454ec12c86fd562b64ccd454c1199846c1b7d158db9ed38"
checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
dependencies = [
"cranelift-codegen",
"libc",
@ -953,9 +952,9 @@ dependencies = [
[[package]]
name = "cranelift-wasm"
version = "0.90.0"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f54959195c47437544a1a4d2602381949a12918e0179bcc82d909cc34cf08dd"
checksum = "e6b8c5e7ffb754093fb89ec4bd4f9dbb9f1c955427299e334917d284745835c2"
dependencies = [
"cranelift-codegen",
"cranelift-entity",
@ -1205,6 +1204,16 @@ dependencies = [
"subtle",
]
[[package]]
name = "directories-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
dependencies = [
"cfg-if 1.0.0",
"dirs-sys-next",
]
[[package]]
name = "dirs"
version = "4.0.0"
@ -1225,6 +1234,17 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi 0.3.9",
]
[[package]]
name = "displaydoc"
version = "0.2.3"
@ -1355,6 +1375,19 @@ dependencies = [
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"atty",
"humantime 2.1.0",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
@ -1472,6 +1505,16 @@ dependencies = [
"tasque",
]
[[package]]
name = "file-per-thread-logger"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21e16290574b39ee41c71aeb90ae960c504ebaf1e2a1c87bd52aa56ed6e1a02f"
dependencies = [
"env_logger 0.9.3",
"log",
]
[[package]]
name = "flate2"
version = "1.0.25"
@ -1575,8 +1618,8 @@ version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a267b6a9304912e018610d53fe07115d8b530b160e85db4d2d3a59f3ddde1aec"
dependencies = [
"io-lifetimes",
"rustix",
"io-lifetimes 0.7.5",
"rustix 0.35.13",
"windows-sys 0.36.1",
]
@ -1872,6 +1915,25 @@ dependencies = [
"tracing",
]
[[package]]
name = "h2_wasi"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "756e9dfbaf90887b69ea8113ef9d04a9fec0ec4ac17b84a95006381f6f7966f9"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio-util_wasi",
"tokio_wasi",
"tracing",
]
[[package]]
name = "handlebars"
version = "4.3.5"
@ -2050,6 +2112,30 @@ dependencies = [
"tokio-native-tls",
]
[[package]]
name = "hyper_wasi"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b903a973bd98c326103ea94336a9ffe44c57c71517d6be7639438021053dc6e"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2_wasi",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"tokio_wasi",
"tower-service",
"tracing",
"want",
"wasmedge_wasi_socket",
]
[[package]]
name = "iana-time-zone"
version = "0.1.53"
@ -2165,7 +2251,7 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5d8c2ab5becd8720e30fd25f8fa5500d8dc3fceadd8378f05859bd7b46fc49"
dependencies = [
"io-lifetimes",
"io-lifetimes 0.7.5",
"windows-sys 0.36.1",
]
@ -2179,6 +2265,16 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys 0.42.0",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -2207,8 +2303,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d508111813f9af3afd2f92758f77e4ed2cc9371b642112c6a48d22eb73105c5"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"io-lifetimes 0.7.5",
"rustix 0.35.13",
"windows-sys 0.36.1",
]
@ -2227,6 +2323,26 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "ittapi"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c4f6ff06169ce7048dac5150b1501c7e3716a929721aeb06b87e51a43e42f4"
dependencies = [
"anyhow",
"ittapi-sys",
"log",
]
[[package]]
name = "ittapi-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87e078cce01485f418bae3beb34dd604aaedf2065502853c7da17fbce8e64eda"
dependencies = [
"cc",
]
[[package]]
name = "jobserver"
version = "0.1.25"
@ -2370,6 +2486,12 @@ version = "0.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
[[package]]
name = "linux-raw-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
[[package]]
name = "local-channel"
version = "0.1.3"
@ -2462,6 +2584,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memfd"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb"
dependencies = [
"rustix 0.36.4",
]
[[package]]
name = "memoffset"
version = "0.6.5"
@ -2542,6 +2673,19 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "mio_wasi"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e260e68b7a4187e52caf00a035aaf7166391c2c2529123fe8229d4d8f86e15a2"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasmedge_wasi_socket",
"windows-sys 0.36.1",
]
[[package]]
name = "miow"
version = "0.2.2"
@ -2967,16 +3111,16 @@ checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
[[package]]
name = "pay_u"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71c9728962c794530dd3e728dd1ad23326dcbfbea34442f2cb0f789ba5e7a112"
dependencies = [
"chrono",
"derive_more",
"dotenv",
"log",
"reqwest",
"reqwest_wasi",
"serde",
"serde_json",
"thiserror",
"tokio",
]
[[package]]
@ -2985,8 +3129,17 @@ version = "0.1.0"
dependencies = [
"config",
"model",
"wasmtime",
]
[[package]]
name = "payment_adapter_pay_u"
version = "0.1.0"
dependencies = [
"pay_u",
"payment_adapter",
"wasmtime",
"wasmtime-api",
"wasmtime-wasi",
]
[[package]]
@ -3002,6 +3155,7 @@ dependencies = [
"model",
"opentelemetry 0.17.0",
"opentelemetry-jaeger",
"payment_adapter",
"rumqttc",
"serde",
"sqlx",
@ -3015,6 +3169,7 @@ dependencies = [
"tracing-subscriber",
"uuid 1.2.2",
"wasmtime",
"wasmtime-wasi",
]
[[package]]
@ -3025,9 +3180,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pest"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f400b0f7905bf702f9f3dc3df5a121b16c54e9e8012c082905fdf09a931861a"
checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
dependencies = [
"thiserror",
"ucd-trie",
@ -3035,9 +3190,9 @@ dependencies = [
[[package]]
name = "pest_derive"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "423c2ba011d6e27b02b482a3707c773d19aec65cc024637aec44e19652e66f63"
checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
dependencies = [
"pest",
"pest_generator",
@ -3045,9 +3200,9 @@ dependencies = [
[[package]]
name = "pest_generator"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e64e6c2c85031c02fdbd9e5c72845445ca0a724d419aa0bc068ac620c9935c1"
checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
dependencies = [
"pest",
"pest_meta",
@ -3058,9 +3213,9 @@ dependencies = [
[[package]]
name = "pest_meta"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57959b91f0a133f89a68be874a5c88ed689c19cd729ecdb5d762ebf16c64d662"
checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
dependencies = [
"once_cell",
"pest",
@ -3123,7 +3278,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"env_logger 0.7.1",
"log",
]
@ -3519,6 +3674,41 @@ dependencies = [
"winreg",
]
[[package]]
name = "reqwest_wasi"
version = "0.11.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c1c0524070b75dc4a924bdaac56d5c874205497fb3132f09f3270e4efb188d"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2_wasi",
"http",
"http-body",
"hyper_wasi",
"ipnet",
"js-sys",
"lazy_static",
"log",
"mime",
"once_cell",
"percent-encoding",
"pin-project-lite",
"serde",
"serde_json",
"serde_urlencoded",
"tokio_wasi",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -3643,14 +3833,28 @@ checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"io-lifetimes 0.7.5",
"itoa",
"libc",
"linux-raw-sys",
"linux-raw-sys 0.0.46",
"once_cell",
"windows-sys 0.42.0",
]
[[package]]
name = "rustix"
version = "0.36.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
dependencies = [
"bitflags",
"errno",
"io-lifetimes 1.0.3",
"libc",
"linux-raw-sys 0.1.3",
"windows-sys 0.42.0",
]
[[package]]
name = "rustls"
version = "0.20.7"
@ -4273,9 +4477,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.104"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
@ -4292,8 +4496,8 @@ dependencies = [
"bitflags",
"cap-fs-ext",
"cap-std",
"io-lifetimes",
"rustix",
"io-lifetimes 0.7.5",
"rustix 0.35.13",
"windows-sys 0.36.1",
"winx",
]
@ -4552,9 +4756,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "1.8.0"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
@ -4624,6 +4828,38 @@ dependencies = [
"tracing",
]
[[package]]
name = "tokio-util_wasi"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e7e921c33dc681c0b01aa4c5aa1bf619f46a7040a1565ddb1f84bc4666c1bd"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio_wasi",
"tracing",
]
[[package]]
name = "tokio_wasi"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68e9a04f238fa1676caa7c897bf1dbe7a82269b675aca14176a028af7a2167d2"
dependencies = [
"autocfg 1.1.0",
"bytes",
"libc",
"memchr",
"mio_wasi",
"num_cpus",
"pin-project-lite",
"socket2",
"wasmedge_wasi_socket",
"winapi 0.3.9",
]
[[package]]
name = "toml"
version = "0.5.9"
@ -4941,9 +5177,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi-cap-std-sync"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe15d7e9ee5bb76cb64b9c29ff00c62642e8552e7f2a8b4758897b0a89a582d"
checksum = "ecbeebb8985a5423f36f976b2f4a0b3c6ce38d7d9a7247e1ce07aa2880e4f29b"
dependencies = [
"anyhow",
"async-trait",
@ -4953,10 +5189,10 @@ dependencies = [
"cap-time-ext",
"fs-set-times",
"io-extras",
"io-lifetimes",
"io-lifetimes 0.7.5",
"is-terminal",
"once_cell",
"rustix",
"rustix 0.35.13",
"system-interface",
"tracing",
"wasi-common",
@ -4965,16 +5201,16 @@ dependencies = [
[[package]]
name = "wasi-common"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e0ef82a2154554def1a220afd48f95cb0f22be343b16930e8957113bd3d967"
checksum = "81e2171f3783fe6600ee24ff6c58ca1b329c55e458cc1622ecc1fd0427648607"
dependencies = [
"anyhow",
"bitflags",
"cap-rand",
"cap-std",
"io-extras",
"rustix",
"rustix 0.35.13",
"thiserror",
"tracing",
"wasmtime",
@ -5050,6 +5286,24 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wasm-encoder"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05632e0a66a6ed8cca593c24223aabd6262f256c3693ad9822c315285f010614"
dependencies = [
"leb128",
]
[[package]]
name = "wasmedge_wasi_socket"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fc4e93009d7e2c2e3d29b65d1f56ef606466673e85fe417808beca50cb608bf"
dependencies = [
"libc",
]
[[package]]
name = "wasmparser"
version = "0.93.0"
@ -5061,11 +5315,12 @@ dependencies = [
[[package]]
name = "wasmtime"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ad9bd12d0823195f6c833f340d8d1df39e2bbf40f5767416560ca7476b97e47"
checksum = "d18265705b1c49218776577d9f301d79ab06888c7f4a32e2ed24e68a55738ce7"
dependencies = [
"anyhow",
"async-trait",
"bincode",
"cfg-if 1.0.0",
"indexmap",
@ -5079,10 +5334,13 @@ dependencies = [
"serde",
"target-lexicon",
"wasmparser",
"wasmtime-cache",
"wasmtime-cranelift",
"wasmtime-environ",
"wasmtime-fiber",
"wasmtime-jit",
"wasmtime-runtime",
"wat",
"windows-sys 0.36.1",
]
@ -5094,18 +5352,38 @@ checksum = "f6db9127057c8be35bf5e4dd3d124b99ffe65db4b5631e701a115e3fb4d92590"
[[package]]
name = "wasmtime-asm-macros"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b6694b753be856b36d47744cdf2bd525bac53d0de5981132d5430bb62c496e4"
checksum = "a201583f6c79b96e74dcce748fa44fb2958f474ef13c93f880ea4d3bed31ae4f"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "wasmtime-cranelift"
version = "3.0.0"
name = "wasmtime-cache"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c55d30708ebc24b6fa2a247807821642967487388845c7fc5320fef1010abe8"
checksum = "3f37efc6945b08fcb634cffafc438dd299bac55a27c836954656c634d3e63c31"
dependencies = [
"anyhow",
"base64",
"bincode",
"directories-next",
"file-per-thread-logger",
"log",
"rustix 0.35.13",
"serde",
"sha2",
"toml",
"windows-sys 0.36.1",
"zstd",
]
[[package]]
name = "wasmtime-cranelift"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe208297e045ea0ee6702be88772ea40f918d55fbd4163981a4699aff034b634"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -5124,9 +5402,9 @@ dependencies = [
[[package]]
name = "wasmtime-environ"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01be016d65ec9200a2d4efbc2ca983bbb7264332e49c11179aaf7587e57d854d"
checksum = "754b97f7441ac780a7fa738db5b9c23c1b70ef4abccd8ad205ada5669d196ba2"
dependencies = [
"anyhow",
"cranelift-entity",
@ -5142,10 +5420,23 @@ dependencies = [
]
[[package]]
name = "wasmtime-jit"
version = "3.0.0"
name = "wasmtime-fiber"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d36042d7962fa1b2a6bfb96d3b33e2283138e7396bc29b2c6970f2a1e80a0ed"
checksum = "e5f54abc960b4a055ba16b942cbbd1da641e0ad44cc97a7608f3d43c069b120e"
dependencies = [
"cc",
"cfg-if 1.0.0",
"rustix 0.35.13",
"wasmtime-asm-macros",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-jit"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32800cb6e29faabab7056593f70a4c00c65c75c365aaf05406933f2169d0c22f"
dependencies = [
"addr2line",
"anyhow",
@ -5153,6 +5444,7 @@ dependencies = [
"cfg-if 1.0.0",
"cpp_demangle",
"gimli",
"ittapi",
"log",
"object",
"rustc-demangle",
@ -5160,6 +5452,7 @@ dependencies = [
"target-lexicon",
"thiserror",
"wasmtime-environ",
"wasmtime-jit-debug",
"wasmtime-jit-icache-coherence",
"wasmtime-runtime",
"windows-sys 0.36.1",
@ -5167,18 +5460,20 @@ dependencies = [
[[package]]
name = "wasmtime-jit-debug"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad4511b8abbdbaf3e9aaa4044ead8bd31b70e2da5e43e2cb91605f871ca23d56"
checksum = "fe057012a0ba6cee3685af1e923d6e0a6cb9baf15fb3ffa4be3d7f712c7dec42"
dependencies = [
"object",
"once_cell",
"rustix 0.35.13",
]
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "2.0.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb7b3e58024d8d395dfc4efbe2a58360a1998565b118b0342b3cf62a4084bde"
checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -5187,9 +5482,9 @@ dependencies = [
[[package]]
name = "wasmtime-runtime"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4034f371135e9e2e81430dda14f6f5a49a222c6557ec4f65301edc093b216d38"
checksum = "09a23b6e138e89594c0189162e524a29e217aec8f9a4e1959a34f74c64e8d17d"
dependencies = [
"anyhow",
"cc",
@ -5198,22 +5493,24 @@ dependencies = [
"libc",
"log",
"mach",
"memfd",
"memoffset 0.6.5",
"paste",
"rand 0.8.5",
"rustix",
"rustix 0.35.13",
"thiserror",
"wasmtime-asm-macros",
"wasmtime-environ",
"wasmtime-fiber",
"wasmtime-jit-debug",
"windows-sys 0.36.1",
]
[[package]]
name = "wasmtime-types"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a770de14a3b5676dfd8a3c06bcab829d9cb58b113911634f3ec3b6960b1d79e3"
checksum = "68ec7615fde8c79737f1345d81f0b18da83b3db929a87b4604f27c932246d1e2"
dependencies = [
"cranelift-entity",
"serde",
@ -5223,9 +5520,9 @@ dependencies = [
[[package]]
name = "wasmtime-wasi"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648d6b4360af358bf2a0688ef7e35d4b413f7185257bf8de6a58f09fb4d7eca1"
checksum = "ca539adf155dca1407aa3656e5661bf2364b1f3ebabc7f0a8bd62629d876acfa"
dependencies = [
"anyhow",
"wasi-cap-std-sync",
@ -5243,6 +5540,27 @@ dependencies = [
"leb128",
]
[[package]]
name = "wast"
version = "50.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2cbb59d4ac799842791fe7e806fa5dbbf6b5554d538e51cc8e176db6ff0ae34"
dependencies = [
"leb128",
"memchr",
"unicode-width",
"wasm-encoder",
]
[[package]]
name = "wat"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "584aaf7a1ecf4d383bbe1a25eeab0cbb8ff96acc6796707ff65cde48f4632f15"
dependencies = [
"wast 50.0.0",
]
[[package]]
name = "web"
version = "0.1.0"
@ -5315,9 +5633,9 @@ dependencies = [
[[package]]
name = "wiggle"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff29f3353b12c949adc6ad6d89edd87f3fa227b1ee1a26f437ae5e9dfe42ba5f"
checksum = "2da09ca5b8bb9278a2123e8c36342166b9aaa55a0dbab18b231f46d6f6ab85bc"
dependencies = [
"anyhow",
"async-trait",
@ -5330,9 +5648,9 @@ dependencies = [
[[package]]
name = "wiggle-generate"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03743b2f04849564d6a2cd6ba32861d93f2d46baddad449473ec399d58b78e3"
checksum = "ba5796f53b429df7d44cfdaae8f6d9cd981d82aec3516561352ca9c5e73ee185"
dependencies = [
"anyhow",
"heck",
@ -5345,9 +5663,9 @@ dependencies = [
[[package]]
name = "wiggle-macro"
version = "3.0.0"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "544319bbf95f2e0fc2c410b2098aff28a885e6cf59d02a67f5647eec1679d4ec"
checksum = "8b830eb7203d48942fb8bc8bb105f76e7d09c33a082d638e990e02143bb2facd"
dependencies = [
"proc-macro2",
"quote",
@ -5514,7 +5832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b01e010390eb263a4518c8cebf86cb67469d1511c00b749a47b64c39e8054d"
dependencies = [
"bitflags",
"io-lifetimes",
"io-lifetimes 0.7.5",
"windows-sys 0.36.1",
]
@ -5527,7 +5845,7 @@ dependencies = [
"anyhow",
"log",
"thiserror",
"wast",
"wast 35.0.2",
]
[[package]]

View File

@ -19,12 +19,14 @@ members = [
"crates/fs_manager",
"crates/lang_provider",
"crates/payment_adapter",
"crates/payment_adapter_pay_u",
# artifacts
# "crates/db-seed",
# "crates/api",
"crates/web",
# vendor
"vendor/t_pay",
"vendor/pay_u",
]
[profile.release]

View File

@ -20,7 +20,7 @@ async-trait = { version = "0.1", features = [] }
bytes = { version = "1.1.0" }
channels = { path = "../channels", features = ['accounts', 'carts', 'emails', 'search'] }
chrono = { version = "0.4", features = ["serde"] }
config = { path = "../config" }
config = { path = "../config", features = ['full'] }
#database_manager = { path = "../database_manager" }
derive_more = { version = "0.99", features = [] }
dotenv = { version = "0.15", features = [] }

View File

@ -3,12 +3,16 @@ name = "config"
version = "0.1.0"
edition = "2021"
[features]
full = ['actix-web', 'cookie']
default = []
[dependencies]
actix-web = { version = "4.0", features = [] }
cookie = { version = "0.16.1", features = ["signed"] }
actix-web = { version = "4.0", features = [], optional = true }
cookie = { version = "0.16.1", features = ["signed"], optional = true }
parking_lot = { version = "0.12", features = [] }
password-hash = { version = "0.4", features = ["alloc"] }
pay_u = { version = '0.1', features = ["single-client"] }
#pay_u = { path = "../../vendor/pay_u", features = ["single-client"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = [] }
thiserror = { version = "1.0" }

View File

@ -99,6 +99,7 @@ impl WebConfig {
.expect("Invalid password hash")
}
#[cfg(feature = "full")]
pub fn session_secret(&self) -> actix_web::cookie::Key {
use actix_web::cookie::Key;

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
wasmtime-wasi = { version = "3.0.0" }
wasmtime-api = { version = "0.4.0" }
config = { path = "../config" }
config = { path = "../config", default-features = false, features = [] }
model = { path = "../model" }
wasmtime = { version = "3.0.1" }
#socket2 = { version = "0.4.7", default-features = false, features = [] }

View File

@ -1,7 +1,15 @@
use std::collections::HashMap;
pub use config::PaymentProviderConfig;
use model::{Price, ProductId, Quantity, QuantityUnit};
pub use model::*;
use wasmtime::WasmResults;
#[derive(Debug)]
#[repr(C)]
pub enum Status {
Success = 0,
Failure = 1,
}
#[derive(Debug)]
pub struct Buyer {
@ -42,7 +50,7 @@ pub struct CreatePayment {
pub trait PaymentAdapter {
fn name() -> &'static str;
fn init(&mut self, config: &PaymentProviderConfig);
fn init(&mut self, config: PaymentProviderConfig);
fn create_payment(&self, msg: CreatePayment);
fn create_payment(&self, msg: CreatePayment) -> Status;
}

View File

@ -0,0 +1,13 @@
[package]
name = "payment_adapter_pay_u"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ['cdylib']
[dependencies]
payment_adapter = { path = "../payment_adapter" }
pay_u = { path = "../../vendor/pay_u" }
wasmtime = { version = "3.0.1" }
wasmtime-api = { version = "0.4.0" }

View File

@ -0,0 +1,28 @@
use payment_adapter::{CreatePayment, PaymentAdapter, PaymentProviderConfig, Status};
use wasmtime::{ValType, WasmParams, WasmResults};
#[derive(Default)]
pub struct PayUAdapter {}
impl PayUAdapter {
pub fn new() -> Self {
Self::default()
}
}
impl PaymentAdapter for PayUAdapter {
fn name() -> &'static str {
"pay_u"
}
fn init(&mut self, config: PaymentProviderConfig) {}
fn create_payment(&self, msg: CreatePayment) -> Status {
Status::Failure
}
}
#[no_mangle]
pub fn adapter() -> PayUAdapter {
PayUAdapter::new()
}

View File

@ -27,7 +27,9 @@ 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'] }
wasmtime-wasi = { version = "3.0.0" }
gumdrop = { version = "0.8.1", features = [] }
payment_adapter = { path = "../payment_adapter" }
[dev-dependencies]
fake = { version = "2.5.0" }

View File

@ -2,6 +2,7 @@ use std::fs::read_dir;
use std::path::PathBuf;
use config::{AppConfig, UpdateConfig};
use payment_adapter::PaymentAdapter;
// mod actions;
// mod context;
@ -31,6 +32,16 @@ async fn main() {
let config = config::default_load(&opts);
let engine = wasmtime::Engine::default();
let mut linker = wasmtime::Linker::new(&engine);
wasmtime_wasi::add_to_linker(&mut linker, |cx| cx).unwrap();
let wasi_ctx = wasmtime_wasi::WasiCtxBuilder::new()
.inherit_env()
.unwrap()
.inherit_stdio()
.inherit_stdio()
.build();
let mut store = wasmtime::Store::new(&engine, wasi_ctx);
{
let adapters_path = config.lock().payment().adapters_path.clone();
@ -42,7 +53,23 @@ async fn main() {
)
});
for file in dir.filter_map(|r| r.map(|r| r.path()).ok()) {
wasmtime::Module::from_file(&engine, file).unwrap();
let module = wasmtime::Module::from_file(&engine, file).unwrap();
let instance = linker.instantiate(&mut store, &module).unwrap();
let fnc =
match instance.get_typed_func::<(), dyn PaymentAdapter, _>(&mut store, "adapter") {
Err(e) => {
tracing::error!("{}", e);
continue;
}
Ok(fnc) => fnc,
};
let adapter = match fnc.call(&mut store, ()) {
Err(e) => {
tracing::error!("{}", e);
continue;
}
Ok(adapter) => adapter,
};
}
}

29
vendor/pay_u/Cargo.toml vendored Normal file
View File

@ -0,0 +1,29 @@
[package]
name = "pay_u"
description = "PayU Rest API wrapper"
version = "0.1.9"
edition = "2021"
license = "MIT"
repository = "https://git.sr.ht/~tsumanu/payu-rs"
authors = ["Tsumanu <adrian.wozniak@ita-prog.pl>"]
categories = ["web-programming", "api-bindings"]
keywords = ["payment", "payu"]
[features]
single-client = []
default = ['single-client']
[dependencies]
#reqwest = { version = "*", features = ["default", "json", "blocking"] }
reqwest_wasi = { version = "*", features = ["default", "json", "blocking"] }
#isahc = { version = "1.7.2", features = [] }
serde = { version = "*", features = ["derive"] }
serde_json = { version = "*" }
chrono = { version = "*", features = ["serde"] }
thiserror = { version = "*" }
log = { version = "*" }
derive_more = { version = "*" }
[dev-dependencies]
tokio = { version = "1.17.0", features = ["full"] }
dotenv = { version = "0.15.0" }

77
vendor/pay_u/src/credit.rs vendored Normal file
View File

@ -0,0 +1,77 @@
//! This module allow to create credit request during create order request
use serde::{Deserialize, Serialize};
use crate::{Address, ShoppingCart};
/// Describe customer during credit request
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Applicant {
/// Applicants email address
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
/// Applicants phone number
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
phone: Option<String>,
/// Applicants first name
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
first_name: Option<String>,
/// Applicants last name
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
last_name: Option<String>,
/// Language code, ISO-639-1 compliant. Denotes the language version of
/// PayU hosted payment page and of e-mail messages sent from PayU to the
/// payer (supported values are here).
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
language: Option<String>,
/// National Identification Number
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
nin: Option<String>,
/// Section containing data about applicants address.
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
address: Option<Address>,
/// Additional information about person applying for credit.
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
additional_info: Option<ApplicantAdditionalInfo>,
}
/// Allow to create credit request
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct Credit {
/// Section containing data of the ordered products
#[serde(skip_serializing_if = "Option::is_none")]
shopping_carts: Option<Vec<ShoppingCart>>,
/// Section containing data of person applying for a credit
#[serde(skip_serializing_if = "Option::is_none")]
applicant: Option<Applicant>,
}
impl Credit {
pub fn with_shopping_carts<ShoppingCarts>(mut self, shopping_carts: ShoppingCarts) -> Self
where
ShoppingCarts: Iterator<Item = ShoppingCart>,
{
self.shopping_carts = Some(shopping_carts.collect());
self
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ApplicantAdditionalInfo {
/// Information whether there were previous, successfully completed orders
/// for applicant.
/// Recommended
#[serde(skip_serializing_if = "Option::is_none")]
has_successfully_finished_order_in_shop: Option<String>,
}

162
vendor/pay_u/src/deserialize.rs vendored Normal file
View File

@ -0,0 +1,162 @@
use std::fmt;
use serde::de::{self, Error, Visitor};
pub(crate) fn deserialize_i32<'de, D>(d: D) -> std::result::Result<i32, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_string(I32Visitor)
}
pub(crate) fn deserialize_i32_newtype<'de, N: From<i32>, D>(
d: D,
) -> std::result::Result<N, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_string(I32Visitor).map(N::from)
}
pub(crate) fn deserialize_u32<'de, D>(d: D) -> std::result::Result<u32, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_string(U32Visitor)
}
struct I32Visitor;
impl<'de> Visitor<'de> for I32Visitor {
type Value = i32;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an integer between -2^31 and 2^31")
}
fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(i32::from(value))
}
fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(value)
}
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
use std::i32;
if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
Ok(value as i32)
} else {
Err(E::custom(format!("i32 out of range: {}", value)))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
if let Ok(value) = v.parse::<i32>() {
Ok(value)
} else {
Err(E::custom(format!("str does not contains valid i32: {}", v)))
}
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
if let Ok(value) = v.parse::<i32>() {
Ok(value)
} else {
Err(E::custom(format!(
"string does not contains valid i32: {}",
v
)))
}
}
// Similar for other methods:
// - visit_i16
// - visit_u8
// - visit_u16
// - visit_u32
// - visit_u64
}
struct U32Visitor;
impl<'de> Visitor<'de> for U32Visitor {
type Value = u32;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an integer between -2^31 and 2^31")
}
fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(u32::from(value))
}
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(value)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use std::u32;
if value >= u64::from(u32::MIN) && value <= u64::from(u32::MAX) {
Ok(value as u32)
} else {
Err(E::custom(format!("i32 out of range: {}", value)))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
if let Ok(value) = v.parse::<u32>() {
Ok(value)
} else {
Err(E::custom(format!("str does not contains valid i32: {}", v)))
}
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
if let Ok(value) = v.parse::<u32>() {
Ok(value)
} else {
Err(E::custom(format!(
"string does not contains valid i32: {}",
v
)))
}
}
// Similar for other methods:
// - visit_i16
// - visit_u8
// - visit_u16
// - visit_u32
// - visit_u64
}

1475
vendor/pay_u/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

161
vendor/pay_u/src/notify.rs vendored Normal file
View File

@ -0,0 +1,161 @@
//! Notification objects. Those objects will be send on notify_url if was given.
//!
//! To enable notifications for a specific payment, specify the notifyUrl
//! parameter in the payment form. Each payment can receive a different URL to
//! which notifications will be sent.
//!
//! Every notification is sent asynchronously. After your system receives a
//! notification with the status COMPLETED, instruct it to ignore any further
//! notifications.
//!
//! After sending a notification, PayU system requires a 200 HTTP status code in
//! response. If it receives a different status code, it will resend the
//! notification. Your system should also take account of situations where a
//! notification is sent several times with the same status. For each repeated
//! notification, response with code 200 should be sent as well.
//!
//! To ensure trusted communication between PayU and your shop, you must verify
//! the signature value available in the OpenPayu-Signature header each time
//! your system receives any notification from a PayU server. Refer to the
//! Verification of notifications signature for more information.
//!
//! Notifications are sent for orders in the following statuses: PENDING,
//! WAITING_FOR_CONFIRMATION, COMPLETED, CANCELED.
//!
//! Note: if you filter IP addresses, remember to allow IPs used by PayU to send
//! the notifications. These are:
//!
//! ### PRODUCTION
//!
//! > 185.68.12.10, 185.68.12.11, 185.68.12.12, 185.68.12.26, 185.68.12.27,
//! > 185.68.12.28
//!
//! ### SANDBOX
//!
//! > 185.68.14.10, 185.68.14.11, 185.68.14.12, 185.68.14.26, 185.68.14.27,
//! > 185.68.14.28
//!
//! ## Payment lifecycle
//!
//! You can configure a separate auto-receive / automatic collection parameter
//! for each payment method via the Management Panel.
//!
//! By default, auto-receive is enabled. The basic payment sequence is as
//! follows:
//!
//! 1) Each successfully authorized payment for an order is captured.
//! 2) The buyer is charged with the order amount.
//! 3) The shop balance is increased by the order amount.
//! 4) PayU calculates its commission to the order.
//!
//! If the auto-receive is turned off, you should capture each order using a PUT
//! method (Order capture) or cancel using DELETE method (Cancellation).
//!
//! If no such action is taken the order is auto-canceled. Automatic
//! cancellation occurs after a number of days indicated for the payment method.
//!
//! <img src="https://developers.payu.com/images/order_statusesV2-en.png" />
use serde::Deserialize;
use super::deserialize;
use crate::OrderId;
/// Payment notification object received on notify_url
///
/// See [crate::req::CreateOrder::notify_url]
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct StatusUpdate {
/// Section containing order object
pub order: Order,
/// Moment of accepting the transaction and adding funds from the
/// transaction to the Shop balance. Format: "%Y-%M-%DT%h:%m:%s%z."
/// Example: "2020-06-09T17:52:04.644+02:00". If the millisecond counter
/// is "000" then milliseconds are not sent and the format changes to:
/// "%Y-%M-%DT%h:%m:%s". Is present only for the status "COMPLETED".
pub local_receipt_date_time: Option<String>,
/// Array of objects related to transaction identification. In case of
/// statuses:
/// * `"WAITING_FOR_CONFIRMATION"` and `"COMPLETED"` - Contains one element
/// with two parameters: name and value,
/// * `"PENDING"` - may contain object with aforementioned parameters or it
/// can be empty.
///
/// Also properties `name`
///
/// Static value. The payment identifier, displayed on transaction
/// statements as "Trans ID" and within the transaction search option in
/// the Management Panel.
///
/// Also properties `value`
///
/// Transaction ID in PayU system (data type - string).
pub properties: Option<Vec<super::Prop>>,
}
impl StatusUpdate {
pub fn status(&self) -> super::PaymentStatus {
self.order.status
}
/// See [crate::req::OrderCreate::ext_order_id]
pub fn ext_order_id(&self) -> &str {
self.order.ext_order_id.as_deref().unwrap_or_default()
}
pub fn has_ext_order_id(&self) -> bool {
self.order.ext_order_id.is_some()
}
}
/// Refund notification object
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RefundUpdate {
pub ext_order_id: String,
pub order_id: OrderId,
pub refund: Refund,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Refund {
pub refund_id: String,
pub amount: String,
pub currency_code: String,
pub status: super::RefundStatus,
pub status_date_time: String,
pub reason: String,
pub reason_description: String,
pub refund_date: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Order {
pub notify_url: Option<String>,
/// Customer client IP address
pub customer_ip: String,
/// Secret pos ip. This is connected to PayU account
#[serde(deserialize_with = "deserialize::deserialize_i32_newtype")]
pub merchant_pos_id: super::MerchantPosId,
/// Transaction description
pub description: String,
/// 3 characters currency identifier, ex. PLN
pub currency_code: String,
/// Total price of the order in pennies (e.g. 1000 is 10.00 EUR).
/// Applies also to currencies without subunits (e.g. 1000 is 10
/// HUF).
#[serde(deserialize_with = "deserialize::deserialize_i32")]
pub total_amount: super::Price,
/// @see [crate::Buyer]
pub buyer: Option<super::Buyer>,
/// List of products
pub products: Vec<super::Product>,
#[serde(skip_serializing)]
pub order_create_date: Option<String>,
pub pay_method: Option<super::PayMethod>,
pub status: super::PaymentStatus,
pub ext_order_id: Option<String>,
}

381
vendor/pay_u/src/req.rs vendored Normal file
View File

@ -0,0 +1,381 @@
//! Objects used to send requests to PayU
use serde::{Deserialize, Serialize};
use crate::credit::Credit;
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Refund {
pub(crate) description: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) amount: Option<super::Price>,
}
impl Refund {
pub fn new<Description>(description: Description, amount: Option<super::Price>) -> Self
where
Description: Into<String>,
{
Self {
description: description.into(),
amount,
}
}
pub fn description(&self) -> &str {
&self.description
}
pub fn amount(&self) -> Option<super::Price> {
self.amount
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct OrderCreate {
/// ID of an order used in merchant system. Order identifier assigned by
/// the merchant. It enables merchants to find a specific order
/// in their system. This value must be unique within a single
/// POS.
pub(crate) ext_order_id: Option<String>,
/// URL to which web hook will be send. It's important to return 200 to
/// all notifications.
///
/// All notifications are send as POST with JSON payload
///
/// Notifications are sent immediately after a payment status changes.
/// If the notification is not received by the Shop application,
/// it will be sent again in accordance with the table below:
///
/// | Attempt | Time |
/// |---------|------|
/// | 1 | immediately |
/// | 2 | 1 minute |
/// | 3 | 2 minutes |
/// | 4 | 5 minutes |
/// | 5 | 10 minutes |
/// | 6 | 30 minutes |
/// | 7 | 1 hour |
/// | 8 | 2 hours |
/// | 9 | 3 hours |
/// | 10| 6 hours |
/// | 11| 9 hours |
/// | 12| 12 hours |
/// | 13| 15 hours |
/// | 14| 18 hours |
/// | 15| 21 hours |
/// | 16| 24 hours |
/// | 17| 36 hours |
/// | 18| 48 hours |
/// | 19| 60 hours |
/// | 20| 72 hours |
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) notify_url: Option<String>,
/// Address for redirecting the customer after payment is commenced. If
/// the payment has not been authorized, error=501 parameter
/// will be added. Please note that no decision regarding
/// payment status should be made depending on the presence or
/// lack of this parameter (to get payment status, wait for
/// notification or retrieve order details).
///
/// IMPORTANT: the address must be compliant with the structure below:
/// <img src="https://developers.payu.com/images/continueUrlStructure_en.png" />
///
/// Please keep in mind:
/// * accepted schemas are http and https,
/// * such elements as port, path, query and fragment are optional,
/// * query values must be encoded.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) continue_url: Option<String>,
/// Payers IP address, e.g. 123.123.123.123. Note: 0.0.0.0 is not
/// accepted.
pub(crate) customer_ip: String,
/// Secret pos ip. This is connected to PayU account
#[serde(
serialize_with = "crate::serialize::serialize_newtype",
deserialize_with = "crate::deserialize::deserialize_i32_newtype"
)]
pub(crate) merchant_pos_id: super::MerchantPosId,
/// Transaction description
pub(crate) description: String,
/// 3 characters currency identifier, ex. PLN
pub(crate) currency_code: String,
/// Total price of the order in pennies (e.g. 1000 is 10.00 EUR).
/// Applies also to currencies without subunits (e.g. 1000 is 10
/// HUF).
#[serde(
serialize_with = "crate::serialize::serialize_i32",
deserialize_with = "crate::deserialize::deserialize_i32"
)]
pub(crate) total_amount: super::Price,
/// @see [crate::Buyer]
pub(crate) buyer: Option<super::Buyer>,
/// List of products
pub(crate) products: Vec<super::Product>,
#[serde(skip_serializing)]
pub(crate) order_create_date: Option<String>,
/// Duration for the validity of an order (in seconds), during which
/// time payment must be made. Default value 86400.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) validity_time: Option<u16>,
/// Additional description of the order.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) additional_description: Option<String>,
/// Text visible on the PayU payment page (max. 80 chars).
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) visible_description: Option<String>,
/// Payment recipient name followed by payment description (order ID,
/// ticket number etc) visible on card statement (max. 22
/// chars). The name should be easy to recognize by the
/// cardholder (e.g "shop.com 124343"). If field
/// is not provided, static name configured by PayU will be used.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) statement_description: Option<String>,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub(crate) muct: Option<super::muct::MultiUseCartToken>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) credit: Option<Credit>,
}
impl OrderCreate {
pub fn build<CustomerIp, Currency, Description>(
buyer: super::Buyer,
customer_ip: CustomerIp,
currency: Currency,
description: Description,
) -> super::Result<Self>
where
CustomerIp: Into<String>,
Currency: Into<String>,
Description: Into<String>,
{
let customer_ip = customer_ip.into();
if &customer_ip == "0.0.0.0" {
return Err(super::Error::CustomerIp);
}
Ok(Self {
ext_order_id: None,
notify_url: None,
continue_url: None,
customer_ip,
merchant_pos_id: 0.into(),
description: description.into(),
currency_code: currency.into(),
total_amount: 0,
buyer: Some(buyer),
products: Vec::new(),
order_create_date: None,
validity_time: None,
additional_description: None,
visible_description: None,
statement_description: None,
muct: None,
credit: None,
})
}
/// ID of an order used in merchant system. Order identifier assigned by
/// the merchant. It enables merchants to find a specific order
/// in their system. This value must be unique within a single
/// POS.
pub fn with_ext_order_id<S: Into<String>>(mut self, ext_order_id: S) -> Self {
self.ext_order_id = Some(ext_order_id.into());
self
}
/// Duration for the validity of an order (in seconds), during which
/// time payment must be made. Default value 86400.
pub fn with_validity_time(mut self, validity_time: u16) -> Self {
self.validity_time = Some(validity_time);
self
}
pub fn with_multi_use_token(
mut self,
recurring: super::muct::Recurring,
card_on_file: super::muct::CardOnFile,
) -> Self {
self.muct = Some(super::muct::MultiUseCartToken {
recurring,
card_on_file,
});
self
}
pub fn with_products<Products>(mut self, products: Products) -> Self
where
Products: Iterator<Item = super::Product>,
{
self.products.extend(products);
self.total_amount = self
.products
.iter()
.fold(0, |agg, p| agg + (p.quantity as i32 * p.unit_price as i32));
self
}
pub fn with_product(mut self, product: super::Product) -> Self {
self.products.push(product);
self.total_amount = self
.products
.iter()
.fold(0, |agg, p| agg + (p.quantity as i32 * p.unit_price as i32));
self
}
/// Description of the an order.
///
/// > This method will override initial description!
pub fn with_description<Description>(mut self, desc: Description) -> Self
where
Description: Into<String>,
{
self.description = String::from(desc.into().trim());
self
}
/// Additional description of the order.
pub fn with_additional_description<S: Into<String>>(
mut self,
additional_description: S,
) -> Self {
self.additional_description = Some(additional_description.into());
self
}
/// Text visible on the PayU payment page (max. 80 chars).
pub fn with_visible_description(mut self, visible_description: &str) -> Self {
let visible_description = if visible_description.len() > 60 {
&visible_description[..60]
} else {
visible_description
};
self.visible_description = Some(String::from(visible_description));
self
}
/// Payment recipient name followed by payment description (order ID,
/// ticket number etc) visible on card statement (max. 22
/// chars). The name should be easy to recognize by the
/// cardholder (e.g "shop.com 124343"). If field
/// is not provided, static name configured by PayU will be used.
pub fn with_statement_description<Description>(mut self, desc: Description) -> Self
where
Description: Into<String>,
{
self.statement_description = Some(String::from(desc.into().trim()));
self
}
/// Add url to which PayU will be able to send http request with payment
/// status updates
///
/// All requests from PayU should receive 200 response!
///
/// See more [crate::res::Order::notify_url]
pub fn with_notify_url<NotifyUrl>(mut self, notify_url: NotifyUrl) -> Self
where
NotifyUrl: Into<String>,
{
self.notify_url = Some(notify_url.into());
self
}
/// Address for redirecting the customer after payment is commenced. If
/// the payment has not been authorized, error=501 parameter
/// will be added. Please note that no decision regarding
/// payment status should be made depending on the presence or
/// lack of this parameter (to get payment status, wait for
/// notification or retrieve order details).
pub fn with_continue_url<ContinueUrl>(mut self, continue_url: ContinueUrl) -> Self
where
ContinueUrl: Into<String>,
{
self.continue_url = Some(continue_url.into());
self
}
/// Section containing credit data. This information is not required,
/// but it is strongly recommended to include it. Otherwise the
/// buyer will be prompted to provide missing data on provider
/// page when payment by Installments or Pay later.
pub fn with_credit(mut self, credit: Credit) -> Self {
self.credit = Some(credit);
self
}
/// URL to which web hook will be send. It's important to return 200 to
/// all notifications.
///
/// All notifications are send as POST with JSON payload
///
/// Notifications are sent immediately after a payment status changes.
/// If the notification is not received by the Shop application,
/// it will be sent again in accordance with the table below:
///
/// | Attempt | Time |
/// |---------|------|
/// | 1 | immediately |
/// | 2 | 1 minute |
/// | 3 | 2 minutes |
/// | 4 | 5 minutes |
/// | 5 | 10 minutes |
/// | 6 | 30 minutes |
/// | 7 | 1 hour |
/// | 8 | 2 hours |
/// | 9 | 3 hours |
/// | 10| 6 hours |
/// | 11| 9 hours |
/// | 12| 12 hours |
/// | 13| 15 hours |
/// | 14| 18 hours |
/// | 15| 21 hours |
/// | 16| 24 hours |
/// | 17| 36 hours |
/// | 18| 48 hours |
/// | 19| 60 hours |
/// | 20| 72 hours |
pub fn notify_url(&self) -> &Option<String> {
&self.notify_url
}
/// Customer IP address from http request received from client
pub fn customer_ip(&self) -> &String {
&self.customer_ip
}
pub fn merchant_pos_id(&self) -> super::MerchantPosId {
self.merchant_pos_id
}
pub fn description(&self) -> &String {
&self.description
}
pub fn currency_code(&self) -> &String {
&self.currency_code
}
pub fn total_amount(&self) -> &super::Price {
&self.total_amount
}
pub fn buyer(&self) -> &Option<super::Buyer> {
&self.buyer
}
pub fn products(&self) -> &[super::Product] {
&self.products
}
pub fn order_create_date(&self) -> &Option<String> {
&self.order_create_date
}
pub(crate) fn with_merchant_pos_id(mut self, merchant_pos_id: super::MerchantPosId) -> Self {
self.merchant_pos_id = merchant_pos_id;
self
}
}

144
vendor/pay_u/src/res.rs vendored Normal file
View File

@ -0,0 +1,144 @@
use crate::{OrderId, Refund, Status};
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrder {
/// Http status as a text
pub status: Status,
/// Client should be redirected to this URI
pub redirect_uri: String,
/// This should be connected to your own order
pub order_id: OrderId,
/// This is YOUR_EXT_ORDER_ID
pub ext_order_id: Option<String>,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RefundDetails {
pub order_id: Option<String>,
pub refund: Option<Refund>,
pub status: Status,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Refunds {
pub refunds: Vec<Refund>,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionPayMethod {
pub value: String,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum CardProfile {
Consumer,
Business,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum CardClassification {
Debit,
Credit,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionCartData {
/// // "543402******4014",
pub card_number_masked: String,
/// MC (MasterCard/Maestro), VS (Visa)
/// Example; "MC"
pub card_scheme: String,
pub card_profile: CardProfile,
pub card_classification: CardClassification,
/// Example: "000"
pub card_response_code: String,
/// Example: "000 - OK"
pub card_response_code_desc: String,
/// Example: "5"
pub card_eci_code: String,
/// Example: "AY",
pub card3ds_status: String,
/// Example: "PL",
pub card_bin_country: String,
/// Example: "MCC0111LL1121"
pub first_transaction_id: String,
}
/// > Installment proposal on the Sandbox environment is not related to the
/// > order amount and always returns data for 480 PLN.
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionCardInstallmentProposal {
/// Example: "5aff3ba8-0c37-4da1-ba4a-4ff24bcc2eed"
pub proposal_id: String,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TransactionCart {
pub cart_data: TransactionCartData,
pub card_installment_proposal: TransactionCardInstallmentProposal,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
pub pay_method: TransactionPayMethod,
pub payment_flow: String,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Transactions {
pub transactions: Vec<Transaction>,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Order {
/// Example: "{orderId}",
pub order_id: super::OrderId,
/// Example: "358766",
pub ext_order_id: Option<String>,
/// Example: "2014-10-27T14:58:17.443+01:00",
pub order_create_date: String,
/// Example: "http://localhost/OrderNotify/",
pub notify_url: Option<String>,
/// Example: "127.0.0.1",
pub customer_ip: String,
/// Example: "145227",
pub merchant_pos_id: String,
/// Example: "New order",
pub description: String,
/// Example: "PLN",
pub currency_code: String,
/// Example: "3200",
pub total_amount: String,
/// Example: "NEW",
pub status: String,
/// Example: `[{"name":"Product1","unitPrice":"1000","quantity":"1"}]`
pub products: Vec<super::Product>,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct OrdersInfo {
pub orders: Vec<Order>,
pub status: Status,
pub properties: Option<Vec<crate::Prop>>,
}
#[derive(serde::Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct OrderInfo {
pub order: Order,
pub status: Status,
pub properties: Option<Vec<crate::Prop>>,
}

25
vendor/pay_u/src/serialize.rs vendored Normal file
View File

@ -0,0 +1,25 @@
use std::fmt::Display;
pub(crate) fn serialize_i32<S>(v: &i32, ser: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.serialize_str(&format!("{v}"))
}
pub(crate) fn serialize_newtype<N: Display, S>(
v: &N,
ser: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.serialize_str(&format!("{v}"))
}
pub(crate) fn serialize_u32<S>(v: &u32, ser: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.serialize_str(&format!("{v}"))
}