diff --git a/.env b/.env index 997de49..4ffda0f 100644 --- a/.env +++ b/.env @@ -23,3 +23,5 @@ SITEMAP_INDEX_HOSTNAME="https://example.com" ACTIVE_GATEWAYS="cod,cash,transfer" # only SK,EN available :). Determines what language the gateway names will be in storefront LOCALE="SK" +# uses https://crates.io/crates/iso_currency +CURRENCIES="EUR" diff --git a/.env.example b/.env.example index a5a63ce..d60974f 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,12 @@ +## COMMON VARIABLES FOR ALL APPS REQUIRED_SALEOR_VERSION="^3.13" APP_API_BASE_URL="http://0.0.0.0:3000" APL="Redis" -APL_URL="redis://localhost:6380/2" +APL_URL="redis://localhost:6379/1" LOG_LEVEL="DEBUG" + +## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP +SITEMAP_TARGET_FOLDER="./temp" # Available fields can be found in ./sitemap-generator/src/queries/event_subjects_updated.rs: ProductUpdate SITEMAP_PRODUCT_TEMPLATE="https://example.com/{product.category.slug}/{product.slug}" # Available fields can be found in ./sitemap-generator/src/queries/event_subjects_updated.rs: CategoryUpdate @@ -13,3 +17,11 @@ SITEMAP_COLLECTION_TEMPLATE="https://example.com/collection/{collection.slug}" SITEMAP_PAGES_TEMPLATE="https://example.com/{page.slug}" # Without trailing "/"! SITEMAP_INDEX_HOSTNAME="https://example.com" + +## THESE VARIABLES ARE FOR SIMPLE-PAYMENT-GATEWAY APP +#To see all possible options, check simple-payment-gateway/src/app:GatewayTypes +ACTIVE_GATEWAYS="cod,cash,transfer" +# only SK,EN available :). Determines what language the gateway names will be in storefront +LOCALE="SK" +# uses https://crates.io/crates/iso_currency +CURRENCIES="EUR" diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml index c844e8e..732d74b 100644 --- a/.github/workflows/rust-clippy.yml +++ b/.github/workflows/rust-clippy.yml @@ -32,7 +32,7 @@ jobs: --all-features --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt -D warnings - continue-on-error: true + continue-on-error: false - name: Upload analysis results to GitHub uses: github/codeql-action/upload-sarif@v1 diff --git a/Cargo.lock b/Cargo.lock index 7c58663..75a4497 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1704,6 +1704,26 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "iso_country" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20633e788d3948ea7336861fdb09ec247f5dae4267e8f0743fa97de26c28624d" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "iso_currency" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f07181be95c82347a07cf4caf43d2acd8a7e8d08ef1db75e10ed5a9aec3c1b" +dependencies = [ + "iso_country", + "serde", + "strum 0.25.0", +] + [[package]] name = "itertools" version = "0.12.1" @@ -2696,14 +2716,15 @@ dependencies = [ "dotenvy", "envy", "http 1.0.0", + "iso_currency", "jsonwebtoken", "redis", "reqwest", "rust_decimal", "serde", "serde_json", - "strum", - "strum_macros", + "strum 0.26.2", + "strum_macros 0.26.1", "tower", "tracing", "tracing-subscriber", @@ -2950,6 +2971,7 @@ dependencies = [ "dotenvy", "enum-iterator", "envy", + "iso_currency", "redis", "rust_decimal", "saleor-app-sdk", @@ -3149,12 +3171,34 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + [[package]] name = "strum" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "strum_macros" version = "0.26.1" diff --git a/Cargo.toml b/Cargo.toml index d53637e..73624e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,4 @@ tower = { version = "0.4.13", features = ["util"] } tower-http = { version = "0.5.2", features = ["fs", "trace"] } cynic-codegen = "3.4.3" rust_decimal = { version = "1.34.3", features = ["serde-float"] } +iso_currency = { version = "0.4.4", features = ["with-serde", "iterator"] } diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 09728bc..705d80c 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -27,6 +27,7 @@ envy.workspace = true dotenvy.workspace = true tower = { workspace = true } rust_decimal = { workspace = true, features = ["serde-float"] } +iso_currency = { workspace = true, features = ["with-serde", "iterator"] } reqwest = { version = "0.11.24", features = ["json"] } jsonwebtoken = "9.2.0" async-trait = "0.1.77" diff --git a/sdk/src/locales.rs b/sdk/src/locales.rs index b5f4e16..2674fd2 100644 --- a/sdk/src/locales.rs +++ b/sdk/src/locales.rs @@ -1,6 +1,7 @@ use serde::{Deserialize, Serialize}; +use strum_macros::EnumString; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, EnumString)] pub enum LocaleCode { Ar, Az, diff --git a/sdk/src/webhooks/sync_response.rs b/sdk/src/webhooks/sync_response.rs index 28f1cfc..b94c935 100644 --- a/sdk/src/webhooks/sync_response.rs +++ b/sdk/src/webhooks/sync_response.rs @@ -1,3 +1,4 @@ +use iso_currency::Currency; use rust_decimal::Decimal; use serde::Serialize; @@ -234,3 +235,23 @@ pub struct ListStoredPaymentMethodsResponse { pub name: Option, pub data: Option, } + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct PaymentGateway { + pub id: String, + pub name: String, + pub currencies: Vec, + pub config: Vec, +} + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ConfigMap { + field: String, + value: serde_json::Value, +} + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct PaymentListGatewaysResponse(pub Vec); diff --git a/simple-payment-gateway/Cargo.toml b/simple-payment-gateway/Cargo.toml index 4a2a98e..5a46443 100644 --- a/simple-payment-gateway/Cargo.toml +++ b/simple-payment-gateway/Cargo.toml @@ -34,6 +34,7 @@ surf.workspace = true cynic = { workspace = true, features = ["http-surf"] } cynic-codegen.workspace = true rust_decimal = { workspace = true, features = ["serde-float"] } +iso_currency = { workspace = true, features = ["with-serde", "iterator"] } const_format = "0.2.32" enum-iterator = "2.0.0" diff --git a/simple-payment-gateway/public/logo.png b/simple-payment-gateway/public/logo.png index f591130..f2c9aa9 100644 Binary files a/simple-payment-gateway/public/logo.png and b/simple-payment-gateway/public/logo.png differ diff --git a/simple-payment-gateway/src/app.rs b/simple-payment-gateway/src/app.rs index 7d862ca..b1dbab6 100644 --- a/simple-payment-gateway/src/app.rs +++ b/simple-payment-gateway/src/app.rs @@ -3,11 +3,15 @@ use axum::{ response::{IntoResponse, Response}, }; use enum_iterator::{all, Sequence}; -use std::sync::Arc; +use iso_currency::Currency; +use std::{str::FromStr, sync::Arc}; use tracing::level_filters::LevelFilter; use tracing_subscriber::EnvFilter; -use saleor_app_sdk::{config::Config, locales::LocaleCode, manifest::AppManifest, SaleorApp}; +use saleor_app_sdk::{ + config::Config, locales::LocaleCode, manifest::AppManifest, + webhooks::sync_response::PaymentGateway, SaleorApp, +}; use serde::Serialize; // Make our own error that wraps `anyhow::Error`. pub struct AppError(anyhow::Error); @@ -79,11 +83,14 @@ pub fn get_active_gateways_from_env() -> anyhow::Result> { //eg: "accreditation,cod,other,transfer" let env_types = std::env::var("ACTIVE_GATEWAYS")?; let locale = std::env::var("LOCALE")?; - let locale = match locale.as_str() { - "SK" => LocaleCode::Sk, - "EN" => LocaleCode::En, - l => unimplemented!("Locale {l} not implemented"), - }; + let locale = LocaleCode::from_str(&locale)?; + let currencies = std::env::var("CURRENCIES")?; + let currencies = currencies.split(",").collect::>(); + let currencies = currencies + .iter() + .map(|c| Currency::from_str(*c)) + .collect::, _>>() + .map_err(|e| anyhow::anyhow!(format!("{:?}", e)))?; let str_types: Vec<_> = env_types.split(',').collect(); let gateway_types = str_types @@ -95,23 +102,25 @@ pub fn get_active_gateways_from_env() -> anyhow::Result> { }) .map(|g| ActiveGateway { gateway_type: g.clone(), - currencies: vec!["EUR".to_owned()], - id: format!("{:?}", &g).to_lowercase(), - config: [], - name: match (g, &locale) { - (GatewayType::COD, LocaleCode::Sk) => "Dobierka".to_owned(), - (GatewayType::Cash, LocaleCode::Sk) => "Hotovosť".to_owned(), - (GatewayType::Transfer, LocaleCode::Sk) => "Bankový prevod".to_owned(), - (GatewayType::Inkaso, LocaleCode::Sk) => "Inkaso".to_owned(), - (GatewayType::Accreditation, LocaleCode::Sk) => "Vzajomný zápočet".to_owned(), - (GatewayType::Other, LocaleCode::Sk) => "Iné".to_owned(), - (GatewayType::COD, LocaleCode::En) => "Cash on delivery".to_owned(), - (GatewayType::Cash, LocaleCode::En) => "Cash".to_owned(), - (GatewayType::Transfer, LocaleCode::En) => "Bank transfer".to_owned(), - (GatewayType::Inkaso, LocaleCode::En) => "Encashment".to_owned(), - (GatewayType::Accreditation, LocaleCode::En) => "Mutual credit".to_owned(), - (GatewayType::Other, LocaleCode::En) => "Other".to_owned(), - (g, l) => unimplemented!("Gateway {:?} in locale {:?} not implemented", g, l), + gateway: PaymentGateway { + currencies: currencies.clone(), + id: format!("{:?}", &g).to_lowercase(), + config: vec![], + name: match (g, &locale) { + (GatewayType::COD, LocaleCode::Sk) => "Dobierka".to_owned(), + (GatewayType::Cash, LocaleCode::Sk) => "Hotovosť".to_owned(), + (GatewayType::Transfer, LocaleCode::Sk) => "Bankový prevod".to_owned(), + (GatewayType::Inkaso, LocaleCode::Sk) => "Inkaso".to_owned(), + (GatewayType::Accreditation, LocaleCode::Sk) => "Vzajomný zápočet".to_owned(), + (GatewayType::Other, LocaleCode::Sk) => "Iné".to_owned(), + (GatewayType::COD, LocaleCode::En) => "Cash on delivery".to_owned(), + (GatewayType::Cash, LocaleCode::En) => "Cash".to_owned(), + (GatewayType::Transfer, LocaleCode::En) => "Bank transfer".to_owned(), + (GatewayType::Inkaso, LocaleCode::En) => "Encashment".to_owned(), + (GatewayType::Accreditation, LocaleCode::En) => "Mutual credit".to_owned(), + (GatewayType::Other, LocaleCode::En) => "Other".to_owned(), + (g, l) => unimplemented!("Gateway {:?} in locale {:?} not implemented", g, l), + }, }, }) .collect::>(); @@ -122,9 +131,5 @@ pub fn get_active_gateways_from_env() -> anyhow::Result> { #[derive(Debug, Clone, Serialize)] pub struct ActiveGateway { pub gateway_type: GatewayType, - pub id: String, - pub name: String, - pub currencies: Vec, - //don't need this one yet - pub config: [(); 0], + pub gateway: PaymentGateway, } diff --git a/simple-payment-gateway/src/routes/webhooks.rs b/simple-payment-gateway/src/routes/webhooks.rs index d21d9c5..42555e7 100644 --- a/simple-payment-gateway/src/routes/webhooks.rs +++ b/simple-payment-gateway/src/routes/webhooks.rs @@ -7,10 +7,11 @@ use saleor_app_sdk::{ webhooks::{ sync_response::{ CancelationRequestedResult, ChargeRequestedResult, - PaymentGatewayInitializeSessionResponse, RefundRequestedResult, - TransactionCancelationRequestedResponse, TransactionChargeRequestedResponse, - TransactionInitializeSessionResponse, TransactionProcessSessionResponse, - TransactionRefundRequestedResponse, TransactionSessionResult, + PaymentGatewayInitializeSessionResponse, PaymentListGatewaysResponse, + RefundRequestedResult, TransactionCancelationRequestedResponse, + TransactionChargeRequestedResponse, TransactionInitializeSessionResponse, + TransactionProcessSessionResponse, TransactionRefundRequestedResponse, + TransactionSessionResult, }, utils::{get_webhook_event_type, EitherWebhookType}, SyncWebhookEventType, @@ -52,6 +53,16 @@ pub async fn webhooks( let event_type = get_webhook_event_type(&headers)?; let res: Json = match event_type { EitherWebhookType::Sync(a) => match a { + SyncWebhookEventType::PaymentListGateways => { + let gateways = state + .active_gateways + .iter() + .cloned() + .map(|g| g.gateway) + .collect::>(); + Json::from(serde_json::to_value(PaymentListGatewaysResponse(gateways))?) + } + SyncWebhookEventType::TransactionCancelationRequested => { let data = serde_json::from_str::(&body)?; Json::from(serde_json::to_value(