lots of small things
This commit is contained in:
parent
768a1cf7bd
commit
332084b105
17 changed files with 785 additions and 29 deletions
9
.env
9
.env
|
@ -1,8 +1,11 @@
|
||||||
|
## COMMON VARIABLES FOR ALL APPS
|
||||||
REQUIRED_SALEOR_VERSION="^3.13"
|
REQUIRED_SALEOR_VERSION="^3.13"
|
||||||
APP_API_BASE_URL="http://10.100.110.234:3000"
|
APP_API_BASE_URL="http://10.100.110.234:3000"
|
||||||
APL="Redis"
|
APL="Redis"
|
||||||
APL_URL="redis://localhost:6380/2"
|
APL_URL="redis://localhost:6380/2"
|
||||||
LOG_LEVEL="DEBUG"
|
LOG_LEVEL="DEBUG"
|
||||||
|
|
||||||
|
## THESE VARIABLES ARE FOR SITEMAP-GENERATOR APP
|
||||||
SITEMAP_TARGET_FOLDER="./temp"
|
SITEMAP_TARGET_FOLDER="./temp"
|
||||||
# Available fields can be found in ./sitemap-generator/src/queries/event_subjects_updated.rs: ProductUpdate
|
# 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}"
|
SITEMAP_PRODUCT_TEMPLATE="https://example.com/{product.category.slug}/{product.slug}"
|
||||||
|
@ -14,3 +17,9 @@ SITEMAP_COLLECTION_TEMPLATE="https://example.com/collection/{collection.slug}"
|
||||||
SITEMAP_PAGES_TEMPLATE="https://example.com/{page.slug}"
|
SITEMAP_PAGES_TEMPLATE="https://example.com/{page.slug}"
|
||||||
# Without trailing "/"!
|
# Without trailing "/"!
|
||||||
SITEMAP_INDEX_HOSTNAME="https://example.com"
|
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"
|
||||||
|
|
27
Cargo.lock
generated
27
Cargo.lock
generated
|
@ -841,6 +841,26 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-iterator"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "600536cfe9e2da0820aa498e570f6b2b9223eec3ce2f835c8ae4861304fa4794"
|
||||||
|
dependencies = [
|
||||||
|
"enum-iterator-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-iterator-derive"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03cdc46ec28bd728e67540c528013c6a10eb69a02eb31078a1bda695438cbfb8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "envy"
|
name = "envy"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -2454,7 +2474,7 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "saleor-app-sdk"
|
name = "saleor-app-sdk"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -2701,6 +2721,7 @@ dependencies = [
|
||||||
"cynic",
|
"cynic",
|
||||||
"cynic-codegen",
|
"cynic-codegen",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
"enum-iterator",
|
||||||
"envy",
|
"envy",
|
||||||
"redis",
|
"redis",
|
||||||
"saleor-app-sdk",
|
"saleor-app-sdk",
|
||||||
|
@ -2901,9 +2922,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum"
|
name = "strum"
|
||||||
version = "0.26.1"
|
version = "0.26.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f"
|
checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[toolchain]
|
|
||||||
channel = "nightly"
|
|
||||||
targets = ["x86_64-unknown-linux-musl"]
|
|
4
rust-toolchain.tomln
Normal file
4
rust-toolchain.tomln
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
|
#targets = ["x86_64-unknown-linux-musl"]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod apl;
|
pub mod apl;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod headers;
|
pub mod headers;
|
||||||
|
pub mod locales;
|
||||||
pub mod manifest;
|
pub mod manifest;
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod webhooks;
|
pub mod webhooks;
|
||||||
|
@ -25,6 +26,7 @@ pub struct AuthData {
|
||||||
pub app_id: String,
|
pub app_id: String,
|
||||||
pub jwks: Option<String>,
|
pub jwks: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for AuthData {
|
impl std::fmt::Display for AuthData {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
|
47
sdk/src/locales.rs
Normal file
47
sdk/src/locales.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum LocaleCode {
|
||||||
|
Ar,
|
||||||
|
Az,
|
||||||
|
Bg,
|
||||||
|
Bn,
|
||||||
|
Ca,
|
||||||
|
Cs,
|
||||||
|
Da,
|
||||||
|
De,
|
||||||
|
El,
|
||||||
|
En,
|
||||||
|
Es,
|
||||||
|
EsCO,
|
||||||
|
Et,
|
||||||
|
Fa,
|
||||||
|
Fr,
|
||||||
|
Hi,
|
||||||
|
Hu,
|
||||||
|
Hy,
|
||||||
|
Id,
|
||||||
|
Is,
|
||||||
|
It,
|
||||||
|
Ja,
|
||||||
|
Ko,
|
||||||
|
Mn,
|
||||||
|
Nb,
|
||||||
|
Nl,
|
||||||
|
Pl,
|
||||||
|
Pt,
|
||||||
|
PtBR,
|
||||||
|
Ro,
|
||||||
|
Ru,
|
||||||
|
Sk,
|
||||||
|
Sl,
|
||||||
|
Sq,
|
||||||
|
Sr,
|
||||||
|
Sv,
|
||||||
|
Th,
|
||||||
|
Tr,
|
||||||
|
Uk,
|
||||||
|
Vi,
|
||||||
|
ZhHans,
|
||||||
|
ZhHant,
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod sync_response;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
223
sdk/src/webhooks/sync_response.rs
Normal file
223
sdk/src/webhooks/sync_response.rs
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
//Why are these few in snake_case but rest is camelCase?
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct CheckoutCalculateTaxesResponse {
|
||||||
|
pub shipping_price_gross_amount: f32,
|
||||||
|
pub shipping_price_net_amount: f32,
|
||||||
|
pub shipping_tax_rate: f32,
|
||||||
|
pub lines: Vec<LinesResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct LinesResponse {
|
||||||
|
pub total_gross_amount: f32,
|
||||||
|
pub total_net_amount: f32,
|
||||||
|
pub tax_rate: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct CheckoutFilterShippingMethodsResponse {
|
||||||
|
pub excluded_methods: Vec<ExcludedMethodsResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct ExcludedMethodsResponse {
|
||||||
|
pub id: String,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct OrderCalculateTaxes(CheckoutCalculateTaxesResponse);
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct OrderFilterShippingMethods(CheckoutFilterShippingMethodsResponse);
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct ShippingListMethodsForCheckout(Vec<ShippingListMethodsForCheckoutVec>);
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
struct ShippingListMethodsForCheckoutVec {
|
||||||
|
pub id: String,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub amount: f32,
|
||||||
|
pub currency: String,
|
||||||
|
pub maximum_delivery_days: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum ChargeRequestedResult {
|
||||||
|
ChargeSuccess,
|
||||||
|
ChargeFailiure,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct TransactionChargeRequestedResponse {
|
||||||
|
pub psp_reference: String,
|
||||||
|
pub result: Option<ChargeRequestedResult>,
|
||||||
|
pub amount: Option<f32>,
|
||||||
|
pub time: Option<String>,
|
||||||
|
pub external_url: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum RefundRequestedResult {
|
||||||
|
RefundSuccess,
|
||||||
|
RefundFailiure,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TransactionRefundRequestedResponse {
|
||||||
|
pub psp_reference: String,
|
||||||
|
pub result: Option<RefundRequestedResult>,
|
||||||
|
pub amount: Option<f32>,
|
||||||
|
pub time: Option<String>,
|
||||||
|
pub external_url: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum CancelationRequestedResult {
|
||||||
|
CancelSuccess,
|
||||||
|
CancelFailiure,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TransactionCancelationRequestedResponse {
|
||||||
|
pub psp_reference: String,
|
||||||
|
pub result: Option<CancelationRequestedResult>,
|
||||||
|
pub amount: Option<f32>,
|
||||||
|
pub time: Option<String>,
|
||||||
|
pub external_url: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct PaymentGatewayInitializeSessionResponse<T: Serialize> {
|
||||||
|
pub data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum TransactionSessionResult {
|
||||||
|
ChargeSuccess,
|
||||||
|
ChargeFailiure,
|
||||||
|
ChargeRequested,
|
||||||
|
ChargeActionRequired,
|
||||||
|
AuthorizationSuccess,
|
||||||
|
AuthorizationFailure,
|
||||||
|
AuthorizationRequested,
|
||||||
|
AuthorizationActionRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TransactionInitializeSessionResponse<T: Serialize> {
|
||||||
|
pub psp_reference: Option<String>,
|
||||||
|
pub data: Option<T>,
|
||||||
|
pub result: TransactionSessionResult,
|
||||||
|
pub amount: f32,
|
||||||
|
pub time: Option<String>,
|
||||||
|
pub external_url: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TransactionProcessSessionResponse<T: Serialize> {
|
||||||
|
pub psp_reference: Option<String>,
|
||||||
|
pub data: Option<T>,
|
||||||
|
pub result: TransactionSessionResult,
|
||||||
|
pub amount: f32,
|
||||||
|
pub time: Option<String>,
|
||||||
|
pub external_url: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum PaymentMethodTokenizationResult {
|
||||||
|
SucessfullyTokenized,
|
||||||
|
AdditionalActionRequired,
|
||||||
|
Pending,
|
||||||
|
FailedToTokenize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PaymentMethodProcessTokenizationSession<T: Serialize> {
|
||||||
|
pub result: PaymentMethodTokenizationResult,
|
||||||
|
/**
|
||||||
|
Should be present when `PaymentMethodTokenizationResult::{SuccessfullyTokenized && AdditionalActionRequired}`
|
||||||
|
*/
|
||||||
|
pub id: Option<String>,
|
||||||
|
pub data: Option<T>,
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct PaymentMethodInitializeTokenizationSession<T: Serialize>(
|
||||||
|
PaymentMethodProcessTokenizationSession<T>,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum PaymentGatewayTokenisationResult {
|
||||||
|
SuccessfullyInitialized,
|
||||||
|
FailedToInitialize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct PaymentGatewayInitializeTokenizationSession<T: Serialize> {
|
||||||
|
pub result: PaymentGatewayTokenisationResult,
|
||||||
|
pub data: Option<T>,
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum StoredPaymentMethodDeleteResult {
|
||||||
|
SucessfullyDeleted,
|
||||||
|
FailedToDelete,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct StoredPaymentMethodDeleteRequested {
|
||||||
|
pub result: StoredPaymentMethodDeleteResult,
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Dahek is Array<"INTERACTIVE"> from app-sdk/../sync-webhook-response-builder.ts:LIST_STORED_PAYMENT_METHODS?
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PaymentMethod<T: Serialize> {
|
||||||
|
pub id: String,
|
||||||
|
pub supported_payment_flows: Vec<T>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub typ: String,
|
||||||
|
pub credit_card_info: Option<CreditCardInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct CreditCardInfo {
|
||||||
|
brand: String,
|
||||||
|
last_digits: String,
|
||||||
|
exp_month: String,
|
||||||
|
exp_year: String,
|
||||||
|
first_digits: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ListStoredPaymentMethodsResponse<T: Serialize, C: Serialize> {
|
||||||
|
payment_methods: Vec<PaymentMethod<C>>,
|
||||||
|
name: Option<String>,
|
||||||
|
data: Option<T>,
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ surf.workspace = true
|
||||||
cynic = { workspace = true, features = ["http-surf"] }
|
cynic = { workspace = true, features = ["http-surf"] }
|
||||||
cynic-codegen.workspace = true
|
cynic-codegen.workspace = true
|
||||||
const_format = "0.2.32"
|
const_format = "0.2.32"
|
||||||
|
enum-iterator = "2.0.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cynic-codegen.workspace = true
|
cynic-codegen.workspace = true
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
|
use enum_iterator::{all, Sequence};
|
||||||
|
use std::{fmt::Display, str::FromStr, sync::Arc};
|
||||||
|
|
||||||
use saleor_app_sdk::{config::Config, manifest::AppManifest, SaleorApp};
|
use saleor_app_sdk::{config::Config, locales::LocaleCode, manifest::AppManifest, SaleorApp};
|
||||||
|
use serde::{
|
||||||
|
de::{self, Visitor},
|
||||||
|
Deserialize, Deserializer, Serialize,
|
||||||
|
};
|
||||||
// Make our own error that wraps `anyhow::Error`.
|
// Make our own error that wraps `anyhow::Error`.
|
||||||
pub struct AppError(anyhow::Error);
|
pub struct AppError(anyhow::Error);
|
||||||
|
|
||||||
|
@ -38,9 +42,66 @@ pub fn trace_to_std(config: &Config) {
|
||||||
.init();
|
.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Sequence, Serialize)]
|
||||||
|
pub enum GatewayType {
|
||||||
|
Accreditation,
|
||||||
|
Cash,
|
||||||
|
/**
|
||||||
|
Acronym for Cash on Delivery
|
||||||
|
*/
|
||||||
|
COD,
|
||||||
|
Inkaso,
|
||||||
|
Other,
|
||||||
|
Transfer,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub saleor_app: Arc<tokio::sync::Mutex<SaleorApp>>,
|
pub saleor_app: Arc<tokio::sync::Mutex<SaleorApp>>,
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub manifest: AppManifest,
|
pub manifest: AppManifest,
|
||||||
|
pub active_gateways: Vec<ActiveGateway>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_active_gateways_from_env() -> anyhow::Result<Vec<ActiveGateway>> {
|
||||||
|
dotenvy::dotenv()?;
|
||||||
|
//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 str_types: Vec<_> = env_types.split(",").collect();
|
||||||
|
let gateway_types = str_types
|
||||||
|
.iter()
|
||||||
|
.zip(all::<GatewayType>())
|
||||||
|
.filter_map(|(s, g)| match format!("{:?}", g).to_lowercase() == *s {
|
||||||
|
true => Some(g),
|
||||||
|
false => None,
|
||||||
|
})
|
||||||
|
.map(|g| )
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct ActiveGateway {
|
||||||
|
pub gateway_type: GatewayType,
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub currencies: Vec<String>,
|
||||||
|
//don't need this one yet
|
||||||
|
pub config: [(); 0],
|
||||||
|
}
|
||||||
|
impl ActiveGateway{
|
||||||
|
fn from_gateway_type(ty: &GatewayType) -> Self {
|
||||||
|
all_currencies =
|
||||||
|
match type {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,11 @@ use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{trace_to_std, AppState},
|
app::{get_active_gateways_from_env, trace_to_std, AppState},
|
||||||
queries::event_transactions::{
|
queries::event_transactions::{
|
||||||
sub_payment_gateway_initialize_session, sub_transaction_charge_requested,
|
sub_list_payment_gateways, sub_payment_gateway_initialize_session,
|
||||||
sub_transaction_initialize_session, sub_transaction_process_session,
|
sub_transaction_charge_requested, sub_transaction_initialize_session,
|
||||||
sub_transaction_refund_requested,
|
sub_transaction_process_session, sub_transaction_refund_requested,
|
||||||
},
|
},
|
||||||
routes::create_routes,
|
routes::create_routes,
|
||||||
};
|
};
|
||||||
|
@ -63,6 +63,12 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.add_sync_event(SyncWebhookEventType::PaymentGatewayInitializeSession)
|
.add_sync_event(SyncWebhookEventType::PaymentGatewayInitializeSession)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
.add_webhook(
|
||||||
|
WebhookManifest::new(&config)
|
||||||
|
.set_query(sub_list_payment_gateways)
|
||||||
|
.add_sync_event(SyncWebhookEventType::PaymentListGateways)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
.add_permissions(vec![
|
.add_permissions(vec![
|
||||||
AppPermission::HandlePayments,
|
AppPermission::HandlePayments,
|
||||||
AppPermission::ManageOrders,
|
AppPermission::ManageOrders,
|
||||||
|
@ -70,7 +76,9 @@ async fn main() -> anyhow::Result<()> {
|
||||||
AppPermission::HandleCheckouts,
|
AppPermission::HandleCheckouts,
|
||||||
])
|
])
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
|
active_gateways: get_active_gateways_from_env()?,
|
||||||
manifest: app_manifest,
|
manifest: app_manifest,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
saleor_app: Arc::new(Mutex::new(saleor_app)),
|
saleor_app: Arc::new(Mutex::new(saleor_app)),
|
||||||
|
|
|
@ -55,6 +55,18 @@ fragment OrderDetails on Order {
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
pub const sub_list_payment_gateways: &str = r#"
|
||||||
|
subscription ListPaymentGateways {
|
||||||
|
event {
|
||||||
|
... on PaymentListGateways {
|
||||||
|
checkout {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
pub const sub_payment_gateway_initialize_session: &str = concatcp!(
|
pub const sub_payment_gateway_initialize_session: &str = concatcp!(
|
||||||
r#"
|
r#"
|
||||||
subscription PaymentGatewayInitializeSession {
|
subscription PaymentGatewayInitializeSession {
|
||||||
|
@ -178,3 +190,246 @@ subscription transactionCancelationRequested {
|
||||||
"#,
|
"#,
|
||||||
fragment_transaction_details
|
fragment_transaction_details
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionRefundRequested")]
|
||||||
|
pub struct TransactionRefundRequested2 {
|
||||||
|
pub action: TransactionAction,
|
||||||
|
pub transaction: Option<TransactionItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionProcessSession")]
|
||||||
|
pub struct TransactionProcessSession2 {
|
||||||
|
pub action: TransactionProcessAction,
|
||||||
|
pub source_object: OrderOrCheckout,
|
||||||
|
pub transaction: TransactionItem,
|
||||||
|
pub data: Option<Json>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct TransactionProcessAction {
|
||||||
|
pub amount: PositiveDecimal,
|
||||||
|
pub action_type: TransactionFlowStrategyEnum,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionInitializeSession")]
|
||||||
|
pub struct TransactionInitializeSession2 {
|
||||||
|
pub data: Option<Json>,
|
||||||
|
pub source_object: OrderOrCheckout,
|
||||||
|
pub transaction: TransactionItem,
|
||||||
|
pub action: TransactionProcessAction2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionProcessAction")]
|
||||||
|
pub struct TransactionProcessAction2 {
|
||||||
|
pub amount: PositiveDecimal,
|
||||||
|
pub currency: String,
|
||||||
|
pub action_type: TransactionFlowStrategyEnum,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionChargeRequested")]
|
||||||
|
pub struct TransactionChargeRequested2 {
|
||||||
|
pub action: TransactionAction,
|
||||||
|
pub transaction: Option<TransactionItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionCancelationRequested")]
|
||||||
|
pub struct TransactionCancelationRequested2 {
|
||||||
|
pub action: TransactionAction,
|
||||||
|
pub transaction: Option<TransactionItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct TransactionItem {
|
||||||
|
pub id: cynic::Id,
|
||||||
|
pub actions: Vec<TransactionActionEnum>,
|
||||||
|
pub external_url: String,
|
||||||
|
pub message: String,
|
||||||
|
pub authorized_amount: Money,
|
||||||
|
pub authorize_pending_amount: Money,
|
||||||
|
pub canceled_amount: Money,
|
||||||
|
pub cancel_pending_amount: Money,
|
||||||
|
pub charged_amount: Money,
|
||||||
|
pub charge_pending_amount: Money,
|
||||||
|
pub refunded_amount: Money,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct TransactionAction {
|
||||||
|
pub amount: Option<PositiveDecimal>,
|
||||||
|
pub action_type: TransactionActionEnum,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct TransactionRefundRequested {
|
||||||
|
pub event: Option<Event>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct TransactionProcessSession {
|
||||||
|
pub event: Option<Event2>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct TransactionInitializeSession {
|
||||||
|
pub event: Option<Event3>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct TransactionChargeRequested {
|
||||||
|
pub event: Option<Event4>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct TransactionCancelationRequested {
|
||||||
|
pub event: Option<Event5>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Subscription")]
|
||||||
|
pub struct PaymentGatewayInitializeSession {
|
||||||
|
pub event: Option<Event6>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "PaymentGatewayInitializeSession")]
|
||||||
|
pub struct PaymentGatewayInitializeSession2 {
|
||||||
|
pub data: Option<Json>,
|
||||||
|
pub amount: Option<PositiveDecimal>,
|
||||||
|
pub source_object: OrderOrCheckout,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct Order {
|
||||||
|
pub checkout_id: Option<cynic::Id>,
|
||||||
|
pub id: cynic::Id,
|
||||||
|
pub status: OrderStatus,
|
||||||
|
pub is_paid: bool,
|
||||||
|
pub payment_status: PaymentChargeStatusEnum,
|
||||||
|
pub charge_status: OrderChargeStatusEnum,
|
||||||
|
pub can_finalize: bool,
|
||||||
|
pub total_balance: Money,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct Money {
|
||||||
|
pub currency: String,
|
||||||
|
pub amount: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
#[cynic(graphql_type = "Event")]
|
||||||
|
pub enum Event6 {
|
||||||
|
PaymentGatewayInitializeSession2(PaymentGatewayInitializeSession2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
#[cynic(graphql_type = "Event")]
|
||||||
|
pub enum Event5 {
|
||||||
|
TransactionCancelationRequested2(TransactionCancelationRequested2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
#[cynic(graphql_type = "Event")]
|
||||||
|
pub enum Event4 {
|
||||||
|
TransactionChargeRequested2(TransactionChargeRequested2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
#[cynic(graphql_type = "Event")]
|
||||||
|
pub enum Event3 {
|
||||||
|
TransactionInitializeSession2(TransactionInitializeSession2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
#[cynic(graphql_type = "Event")]
|
||||||
|
pub enum Event2 {
|
||||||
|
TransactionProcessSession2(TransactionProcessSession2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
pub enum Event {
|
||||||
|
TransactionRefundRequested2(TransactionRefundRequested2),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InlineFragments, Debug)]
|
||||||
|
pub enum OrderOrCheckout {
|
||||||
|
Order(Order),
|
||||||
|
#[cynic(fallback)]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum OrderChargeStatusEnum {
|
||||||
|
None,
|
||||||
|
Partial,
|
||||||
|
Full,
|
||||||
|
Overcharged,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum OrderStatus {
|
||||||
|
Draft,
|
||||||
|
Unconfirmed,
|
||||||
|
Unfulfilled,
|
||||||
|
PartiallyFulfilled,
|
||||||
|
PartiallyReturned,
|
||||||
|
Returned,
|
||||||
|
Fulfilled,
|
||||||
|
Canceled,
|
||||||
|
Expired,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum PaymentChargeStatusEnum {
|
||||||
|
NotCharged,
|
||||||
|
Pending,
|
||||||
|
PartiallyCharged,
|
||||||
|
FullyCharged,
|
||||||
|
PartiallyRefunded,
|
||||||
|
FullyRefunded,
|
||||||
|
Refused,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum TransactionActionEnum {
|
||||||
|
Charge,
|
||||||
|
Refund,
|
||||||
|
Cancel,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum TransactionFlowStrategyEnum {
|
||||||
|
Authorization,
|
||||||
|
Charge,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Scalar, Debug, Clone)]
|
||||||
|
#[cynic(graphql_type = "JSON")]
|
||||||
|
pub struct Json(pub String);
|
||||||
|
|
||||||
|
#[derive(cynic::Scalar, Debug, Clone)]
|
||||||
|
pub struct PositiveDecimal(pub String);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#[cynic::schema("saleor")]
|
||||||
|
mod schema {}
|
||||||
/*
|
/*
|
||||||
mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
|
mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
|
||||||
transactionUpdate(id: $id, transaction: $transaction) {
|
transactionUpdate(id: $id, transaction: $transaction) {
|
||||||
|
@ -15,3 +17,85 @@ mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#[derive(cynic::QueryVariables, Debug)]
|
||||||
|
pub struct TransactionUpdateVariables<'a> {
|
||||||
|
pub id: &'a cynic::Id,
|
||||||
|
pub transaction: Option<TransactionUpdateInput<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Mutation", variables = "TransactionUpdateVariables")]
|
||||||
|
pub struct TransactionUpdate {
|
||||||
|
#[arguments(id: $id, transaction: $transaction)]
|
||||||
|
pub transaction_update: Option<TransactionUpdate2>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "TransactionUpdate")]
|
||||||
|
pub struct TransactionUpdate2 {
|
||||||
|
pub transaction: Option<TransactionItem>,
|
||||||
|
pub errors: Vec<TransactionUpdateError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct TransactionUpdateError {
|
||||||
|
pub field: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
|
pub code: TransactionUpdateErrorCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct TransactionItem {
|
||||||
|
pub id: cynic::Id,
|
||||||
|
pub actions: Vec<TransactionActionEnum>,
|
||||||
|
pub external_url: String,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum TransactionActionEnum {
|
||||||
|
Charge,
|
||||||
|
Refund,
|
||||||
|
Cancel,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Enum, Clone, Copy, Debug)]
|
||||||
|
pub enum TransactionUpdateErrorCode {
|
||||||
|
Invalid,
|
||||||
|
GraphqlError,
|
||||||
|
NotFound,
|
||||||
|
IncorrectCurrency,
|
||||||
|
MetadataKeyRequired,
|
||||||
|
Unique,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InputObject, Debug)]
|
||||||
|
pub struct TransactionUpdateInput<'a> {
|
||||||
|
pub name: Option<&'a str>,
|
||||||
|
pub message: Option<&'a str>,
|
||||||
|
pub psp_reference: Option<&'a str>,
|
||||||
|
pub available_actions: Option<Vec<TransactionActionEnum>>,
|
||||||
|
pub amount_authorized: Option<MoneyInput<'a>>,
|
||||||
|
pub amount_charged: Option<MoneyInput<'a>>,
|
||||||
|
pub amount_refunded: Option<MoneyInput<'a>>,
|
||||||
|
pub amount_canceled: Option<MoneyInput<'a>>,
|
||||||
|
pub metadata: Option<Vec<MetadataInput<'a>>>,
|
||||||
|
pub private_metadata: Option<Vec<MetadataInput<'a>>>,
|
||||||
|
pub external_url: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InputObject, Debug)]
|
||||||
|
pub struct MoneyInput<'a> {
|
||||||
|
pub currency: &'a str,
|
||||||
|
pub amount: PositiveDecimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::InputObject, Debug)]
|
||||||
|
pub struct MetadataInput<'a> {
|
||||||
|
pub key: &'a str,
|
||||||
|
pub value: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::Scalar, Debug, Clone)]
|
||||||
|
pub struct PositiveDecimal(pub String);
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn create_routes(state: AppState) -> Router {
|
||||||
(StatusCode::NOT_FOUND, "Not found")
|
(StatusCode::NOT_FOUND, "Not found")
|
||||||
}
|
}
|
||||||
let service = handle_404.into_service();
|
let service = handle_404.into_service();
|
||||||
let serve_dir = ServeDir::new("saleor-app-template/public").not_found_service(service);
|
let serve_dir = ServeDir::new("simple-payment-gateway/public").not_found_service(service);
|
||||||
|
|
||||||
Router::new()
|
Router::new()
|
||||||
.layer(middleware::from_fn(webhook_signature_verifier))
|
.layer(middleware::from_fn(webhook_signature_verifier))
|
||||||
|
|
|
@ -5,7 +5,7 @@ use axum::{
|
||||||
http::{HeaderMap, StatusCode},
|
http::{HeaderMap, StatusCode},
|
||||||
};
|
};
|
||||||
use saleor_app_sdk::{AuthData, AuthToken};
|
use saleor_app_sdk::{AuthData, AuthToken};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
use crate::app::{AppError, AppState};
|
use crate::app::{AppError, AppState};
|
||||||
|
|
||||||
|
@ -29,12 +29,25 @@ pub async fn register(
|
||||||
let auth_data = AuthData {
|
let auth_data = AuthData {
|
||||||
jwks: None,
|
jwks: None,
|
||||||
token: auth_token.auth_token,
|
token: auth_token.auth_token,
|
||||||
domain: Some(state.config.app_api_base_url),
|
domain: Some(state.config.app_api_base_url.clone()),
|
||||||
app_id: state.manifest.id,
|
app_id: state.manifest.id.clone(),
|
||||||
saleor_api_url: saleor_api_url.clone(),
|
saleor_api_url: saleor_api_url.clone(),
|
||||||
};
|
};
|
||||||
app.apl.set(auth_data).await?;
|
app.apl.set(auth_data.clone()).await?;
|
||||||
|
//unlock the mutex guard so state isn't borrowed anymore and it can move
|
||||||
|
std::mem::drop(app);
|
||||||
info!("registered app for{:?}", &saleor_api_url);
|
info!("registered app for{:?}", &saleor_api_url);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
match register_active_gateways(&state, auth_data).await {
|
||||||
|
Ok(_) => info!("Payment gateways registered"),
|
||||||
|
Err(e) => error!("Failed registering gateways, {e}"),
|
||||||
|
};
|
||||||
|
});
|
||||||
Ok(StatusCode::OK)
|
Ok(StatusCode::OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn register_active_gateways(state: &AppState, auth_data: AuthData) -> anyhow::Result<()> {
|
||||||
|
// Maybe AppFetch manifest? Tho I might not need to since I already have it
|
||||||
|
// AppsInstallations to see if it's still installing
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use axum::{
|
use axum::{
|
||||||
|
body::Body,
|
||||||
extract::State,
|
extract::State,
|
||||||
http::{HeaderMap, StatusCode},
|
http::{HeaderMap, StatusCode},
|
||||||
|
response::Response,
|
||||||
|
Json,
|
||||||
};
|
};
|
||||||
use saleor_app_sdk::{
|
use saleor_app_sdk::{
|
||||||
headers::SALEOR_API_URL_HEADER,
|
headers::SALEOR_API_URL_HEADER,
|
||||||
|
@ -10,15 +15,20 @@ use saleor_app_sdk::{
|
||||||
SyncWebhookEventType,
|
SyncWebhookEventType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
use crate::app::{AppError, AppState};
|
use crate::{
|
||||||
|
app::{ActiveGateway, AppError, AppState},
|
||||||
|
queries::event_transactions::PaymentGatewayInitializeSession,
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn webhooks(
|
pub async fn webhooks(
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<StatusCode, AppError> {
|
) -> Result<Json<Value>, AppError> {
|
||||||
debug!("/api/webhooks");
|
debug!("/api/webhooks");
|
||||||
debug!("req: {:?}", body);
|
debug!("req: {:?}", body);
|
||||||
debug!("headers: {:?}", headers);
|
debug!("headers: {:?}", headers);
|
||||||
|
@ -29,30 +39,47 @@ pub async fn webhooks(
|
||||||
.to_str()?
|
.to_str()?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let event_type = get_webhook_event_type(&headers)?;
|
let event_type = get_webhook_event_type(&headers)?;
|
||||||
match event_type {
|
let res: Json<Value> = match event_type {
|
||||||
EitherWebhookType::Sync(a) => match a {
|
EitherWebhookType::Sync(a) => match a {
|
||||||
SyncWebhookEventType::PaymentGatewayInitializeSession => {
|
SyncWebhookEventType::PaymentGatewayInitializeSession => {
|
||||||
initialize_gateway(&state, &url).await?;
|
Json::from(serde_json::to_value(JsonResponse {
|
||||||
|
data: JsonResponseData {
|
||||||
|
current_gateway: ActiveGateway::COD,
|
||||||
|
},
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
SyncWebhookEventType::TransactionProcessSession
|
SyncWebhookEventType::TransactionProcessSession
|
||||||
| SyncWebhookEventType::TransactionChargeRequested
|
| SyncWebhookEventType::TransactionChargeRequested
|
||||||
| SyncWebhookEventType::TransactionRefundRequested
|
| SyncWebhookEventType::TransactionRefundRequested
|
||||||
| SyncWebhookEventType::TransactionInitializeSession => {
|
| SyncWebhookEventType::TransactionInitializeSession => {
|
||||||
update_transaction_response(&state, &url).await?;
|
update_transaction_response(&state, &url).await?;
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => Json::from(Value::from_str("")?),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => Json::from(Value::from_str("")?),
|
||||||
}
|
};
|
||||||
|
|
||||||
info!("got webhooks!");
|
info!("got webhooks!");
|
||||||
Ok(StatusCode::OK)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn initialize_gateway(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
#[derive(Serialize, Clone, Debug)]
|
||||||
todo!()
|
pub struct JsonResponse {
|
||||||
|
data: JsonResponseData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone, Debug)]
|
||||||
|
pub struct JsonResponseData {
|
||||||
|
current_gateway: ActiveGateway,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_transaction_response(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
async fn update_transaction_response(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn new_transaction_response(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
||||||
|
debug!("Creating new transaction");
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ pub fn create_routes(state: AppState) -> Router {
|
||||||
//TODO : Fix this relative path issue in workspaces
|
//TODO : Fix this relative path issue in workspaces
|
||||||
let serve_dir = ServeDir::new("./sitemap-generator/public").not_found_service(service);
|
let serve_dir = ServeDir::new("./sitemap-generator/public").not_found_service(service);
|
||||||
|
|
||||||
|
//TODO Query for everything using the app auth token
|
||||||
|
//TODO "Failed fetching initial products: More than one channel exists, please spocify which
|
||||||
|
//one"
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/api/webhooks", any(webhooks))
|
.route("/api/webhooks", any(webhooks))
|
||||||
.layer(middleware::from_fn(webhook_signature_verifier))
|
.layer(middleware::from_fn(webhook_signature_verifier))
|
||||||
|
|
Loading…
Reference in a new issue