before adding GH CI
This commit is contained in:
parent
ee34b1bf22
commit
f6b1977057
23 changed files with 597 additions and 64 deletions
35
.github/rust.yml
vendored
35
.github/rust.yml
vendored
|
@ -1,35 +0,0 @@
|
|||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Run Linter
|
||||
run: cargo fmt -- --check && cargo clippy --all-targets --all-features -- -D warnings
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
46
Cargo.lock
generated
46
Cargo.lock
generated
|
@ -535,6 +535,26 @@ version = "0.4.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673"
|
||||
dependencies = [
|
||||
"const_format_proc_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_format_proc_macros"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.14.4"
|
||||
|
@ -2674,6 +2694,26 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "simple-payment-gateway"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"const_format",
|
||||
"cynic",
|
||||
"cynic-codegen",
|
||||
"dotenvy",
|
||||
"envy",
|
||||
"redis",
|
||||
"saleor-app-sdk",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"surf",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-serde",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
|
@ -3406,6 +3446,12 @@ dependencies = [
|
|||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -23,7 +23,7 @@ to use in your project inside this repo, create a new workspace member and add `
|
|||
|
||||
## Creating a new Saleor App from template
|
||||
|
||||
If using the `saleor-app-template`, create a new workspace member `cargo new <project-name>`, then `cp saleor-app-template/* <project-name>`.
|
||||
If using the `saleor-app-template`, create a new workspace member `cargo new <project-name>`,`rm -rf <project-name>/*` then `cp -r app-template/* <project-name>/`.
|
||||
|
||||
## Adding new dependencies
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
To update the schema, you can download it from https://raw.githubusercontent.com/saleor/saleor/main/saleor/graphql/schema.graphql
|
|
@ -25,27 +25,3 @@ pub struct SaleorHeaders<'a> {
|
|||
#[serde(rename = "content-length")]
|
||||
content_length: u16,
|
||||
}
|
||||
|
||||
/* TODO!
|
||||
impl SaleorHeaders {
|
||||
pub fn verify(&self, payload: &str) -> anyhow::Result<()> {
|
||||
/*
|
||||
if let Some(saleor_signature) = self.signature {
|
||||
let split: Vec<String> = saleor_signature.split(".").collect();
|
||||
let header = split.get(0);
|
||||
let signature = split.get(2);
|
||||
if let Some(header) = header {
|
||||
if let Some(signature) = signature {
|
||||
let jws = jose_jws::Signature {
|
||||
signature: signature.into(),
|
||||
header,
|
||||
protected: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@ pub enum AppPermission {
|
|||
ManageGiftCard,
|
||||
ManageMenus,
|
||||
ManageOrders,
|
||||
ManageOrdersImport,
|
||||
ManagePages,
|
||||
ManagePageTypesAndAttributes,
|
||||
HandlePayments,
|
||||
|
|
|
@ -2,5 +2,38 @@
|
|||
name = "simple-payment-gateway"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Djkáťo <djkatovfx@gmail.com>"]
|
||||
description = "Payment gateway that adds payment methods that don't need actual verification: Cash on delivery, Cash on warehouse pickup, bank tranfer."
|
||||
homepage = "https://github.com/djkato/saleor-app-rs-template"
|
||||
repository = "https://github.com/djkato/saleor-app-rs-template"
|
||||
documentation = "https://github.com/djkato/saleor-app-rs-template"
|
||||
keywords = ["saleor", "sdk", "plugin", "template"]
|
||||
categories = ["api-bindings", "web-programming::http-server"]
|
||||
license = "PolyForm-Noncommercial-1.0.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
redis = { workspace = true, features = [
|
||||
"aio",
|
||||
"tokio-comp",
|
||||
"connection-manager",
|
||||
] }
|
||||
envy.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-serde.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
dotenvy.workspace = true
|
||||
axum.workspace = true
|
||||
saleor-app-sdk.workspace = true
|
||||
tower = { workspace = true, features = ["util"] }
|
||||
tower-http = { workspace = true, features = ["fs", "trace"] }
|
||||
surf.workspace = true
|
||||
cynic = { workspace = true, features = ["http-surf"] }
|
||||
cynic-codegen.workspace = true
|
||||
const_format = "0.2.32"
|
||||
|
||||
[build-dependencies]
|
||||
cynic-codegen.workspace = true
|
||||
|
|
19
simple-payment-gateway/Dockerfile
Normal file
19
simple-payment-gateway/Dockerfile
Normal file
|
@ -0,0 +1,19 @@
|
|||
FROM lukemathwalker/cargo-chef:latest as chef
|
||||
WORKDIR /app
|
||||
|
||||
FROM chef AS planner
|
||||
COPY ./Cargo.toml ./Cargo.lock ./
|
||||
COPY ./src ./src
|
||||
RUN cargo chef prepare
|
||||
|
||||
FROM chef AS builder
|
||||
COPY --from=planner /app/recipe.json .
|
||||
RUN cargo chef cook --release
|
||||
COPY . .
|
||||
RUN cargo build --release
|
||||
RUN mv ./target/release/saleor-app-template ./app
|
||||
|
||||
FROM debian:stable-slim AS runtime
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/app /usr/local/bin/
|
||||
ENTRYPOINT ["/usr/local/bin/app"]
|
4
simple-payment-gateway/README.md
Normal file
4
simple-payment-gateway/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Unofficial Saleor App Template
|
||||
|
||||
To update the saleor schema, you can download it from [here](https://raw.githubusercontent.com/saleor/saleor/main/saleor/graphql/schema.graphql) and put into schema/schema.graphql
|
||||
To generate typings for events and gql queries, use: https://generator.cynic-rs.dev/
|
7
simple-payment-gateway/build.rs
Normal file
7
simple-payment-gateway/build.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
fn main() {
|
||||
cynic_codegen::register_schema("saleor")
|
||||
.from_sdl_file("schema/schema.graphql")
|
||||
.unwrap()
|
||||
.as_default()
|
||||
.unwrap();
|
||||
}
|
BIN
simple-payment-gateway/public/logo.png
Normal file
BIN
simple-payment-gateway/public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
46
simple-payment-gateway/src/app.rs
Normal file
46
simple-payment-gateway/src/app.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
|
||||
use saleor_app_sdk::{config::Config, manifest::AppManifest, SaleorApp};
|
||||
// Make our own error that wraps `anyhow::Error`.
|
||||
pub struct AppError(anyhow::Error);
|
||||
|
||||
// Tell axum how to convert `AppError` into a response.
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Something went wrong: {}", self.0),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into
|
||||
// `Result<_, AppError>`. That way you don't need to do that manually.
|
||||
impl<E> From<E> for AppError
|
||||
where
|
||||
E: Into<anyhow::Error>,
|
||||
{
|
||||
fn from(err: E) -> Self {
|
||||
Self(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trace_to_std(config: &Config) {
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(config.log_level)
|
||||
.with_target(false)
|
||||
.init();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppState {
|
||||
pub saleor_app: Arc<tokio::sync::Mutex<SaleorApp>>,
|
||||
pub config: Config,
|
||||
pub manifest: AppManifest,
|
||||
}
|
|
@ -1,3 +1,94 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![feature(let_chains)]
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
mod app;
|
||||
mod queries;
|
||||
mod routes;
|
||||
|
||||
use anyhow::Context;
|
||||
use saleor_app_sdk::{
|
||||
config::Config,
|
||||
manifest::{AppManifest, AppPermission},
|
||||
webhooks::{SyncWebhookEventType, WebhookManifest},
|
||||
SaleorApp,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
app::{trace_to_std, AppState},
|
||||
queries::event_transactions::{
|
||||
sub_payment_gateway_initialize_session, sub_transaction_charge_requested,
|
||||
sub_transaction_initialize_session, sub_transaction_process_session,
|
||||
sub_transaction_refund_requested,
|
||||
},
|
||||
routes::create_routes,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let config = Config::load()?;
|
||||
trace_to_std(&config);
|
||||
|
||||
let saleor_app = SaleorApp::new(&config)?;
|
||||
|
||||
let app_manifest = AppManifest::new(&config)
|
||||
.add_webhook(
|
||||
WebhookManifest::new(&config)
|
||||
.set_query(sub_transaction_process_session)
|
||||
.add_sync_event(SyncWebhookEventType::TransactionProcessSession)
|
||||
.build(),
|
||||
)
|
||||
.add_webhook(
|
||||
WebhookManifest::new(&config)
|
||||
.set_query(sub_transaction_charge_requested)
|
||||
.add_sync_event(SyncWebhookEventType::TransactionChargeRequested)
|
||||
.build(),
|
||||
)
|
||||
.add_webhook(
|
||||
WebhookManifest::new(&config)
|
||||
.set_query(sub_transaction_refund_requested)
|
||||
.add_sync_event(SyncWebhookEventType::TransactionRefundRequested)
|
||||
.build(),
|
||||
)
|
||||
.add_webhook(
|
||||
WebhookManifest::new(&config)
|
||||
.set_query(sub_transaction_initialize_session)
|
||||
.add_sync_event(SyncWebhookEventType::TransactionInitializeSession)
|
||||
.build(),
|
||||
)
|
||||
.add_webhook(
|
||||
WebhookManifest::new(&config)
|
||||
.set_query(sub_payment_gateway_initialize_session)
|
||||
.add_sync_event(SyncWebhookEventType::PaymentGatewayInitializeSession)
|
||||
.build(),
|
||||
)
|
||||
.add_permissions(vec![
|
||||
AppPermission::HandlePayments,
|
||||
AppPermission::ManageOrders,
|
||||
AppPermission::ManageCheckouts,
|
||||
AppPermission::HandleCheckouts,
|
||||
])
|
||||
.build();
|
||||
let app_state = AppState {
|
||||
manifest: app_manifest,
|
||||
config: config.clone(),
|
||||
saleor_app: Arc::new(Mutex::new(saleor_app)),
|
||||
};
|
||||
let app = create_routes(app_state);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(
|
||||
&config
|
||||
.app_api_base_url
|
||||
.split("//")
|
||||
.collect::<Vec<_>>()
|
||||
.get(1)
|
||||
.context("APP_API_BASE_URL invalid format")?,
|
||||
)
|
||||
.await?;
|
||||
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||
match axum::serve(listener, app).await {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => anyhow::bail!(e),
|
||||
}
|
||||
}
|
||||
|
|
180
simple-payment-gateway/src/queries/event_transactions.rs
Normal file
180
simple-payment-gateway/src/queries/event_transactions.rs
Normal file
|
@ -0,0 +1,180 @@
|
|||
use const_format::concatcp;
|
||||
#[cynic::schema("saleor")]
|
||||
mod schema {}
|
||||
|
||||
pub const fragment_transaction_details: &str = r#"
|
||||
fragment TransactionDetails on TransactionItem {
|
||||
id
|
||||
actions
|
||||
externalUrl
|
||||
message
|
||||
authorizedAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
authorizePendingAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
canceledAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
cancelPendingAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
chargedAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
chargePendingAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
refundedAmount {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
pub const fragment_order_details: &str = r#"
|
||||
fragment OrderDetails on Order {
|
||||
checkoutId
|
||||
id
|
||||
status
|
||||
isPaid
|
||||
paymentStatus
|
||||
chargeStatus
|
||||
canFinalize
|
||||
totalBalance {
|
||||
currency
|
||||
amount
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
pub const sub_payment_gateway_initialize_session: &str = concatcp!(
|
||||
r#"
|
||||
subscription PaymentGatewayInitializeSession {
|
||||
event {
|
||||
... on PaymentGatewayInitializeSession {
|
||||
data
|
||||
amount
|
||||
sourceObject {
|
||||
...OrderDetails
|
||||
}
|
||||
amount
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_order_details
|
||||
);
|
||||
|
||||
pub const sub_transaction_initialize_session: &str = concatcp!(
|
||||
r#"
|
||||
subscription transactionInitializeSession {
|
||||
event {
|
||||
... on TransactionInitializeSession {
|
||||
data
|
||||
sourceObject {
|
||||
...OrderDetails
|
||||
}
|
||||
transaction {
|
||||
...TransactionDetails
|
||||
}
|
||||
action {
|
||||
amount
|
||||
currency
|
||||
actionType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_order_details,
|
||||
fragment_transaction_details
|
||||
);
|
||||
|
||||
pub const sub_transaction_process_session: &str = concatcp!(
|
||||
r#"
|
||||
subscription transactionProcessSession {
|
||||
event {
|
||||
... on TransactionProcessSession {
|
||||
action {
|
||||
amount
|
||||
actionType
|
||||
}
|
||||
sourceObject {
|
||||
...OrderDetails
|
||||
}
|
||||
transaction {
|
||||
...TransactionDetails
|
||||
}
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_order_details,
|
||||
fragment_transaction_details
|
||||
);
|
||||
|
||||
pub const sub_transaction_charge_requested: &str = concatcp!(
|
||||
r#"
|
||||
subscription transactionChargeRequested {
|
||||
event {
|
||||
... on TransactionChargeRequested {
|
||||
action {
|
||||
amount
|
||||
actionType
|
||||
}
|
||||
transaction {
|
||||
...TransactionDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_transaction_details
|
||||
);
|
||||
|
||||
pub const sub_transaction_refund_requested: &str = concatcp!(
|
||||
r#"
|
||||
subscription transactionRefundRequested {
|
||||
event {
|
||||
... on TransactionRefundRequested {
|
||||
action {
|
||||
amount
|
||||
actionType
|
||||
}
|
||||
transaction {
|
||||
...TransactionDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_transaction_details
|
||||
);
|
||||
|
||||
pub const sub_transaction_cancelation_requested: &str = concatcp!(
|
||||
r#"
|
||||
subscription transactionCancelationRequested {
|
||||
event {
|
||||
... on TransactionCancelationRequested {
|
||||
action {
|
||||
amount
|
||||
actionType
|
||||
}
|
||||
transaction {
|
||||
...TransactionDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
fragment_transaction_details
|
||||
);
|
3
simple-payment-gateway/src/queries/mod.rs
Normal file
3
simple-payment-gateway/src/queries/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod event_transactions;
|
||||
pub mod mutation_transaction_update;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
mutation transactionUpdate($id: ID!, $transaction: TransactionUpdateInput) {
|
||||
transactionUpdate(id: $id, transaction: $transaction) {
|
||||
transaction {
|
||||
id
|
||||
actions
|
||||
externalUrl
|
||||
message
|
||||
}
|
||||
errors {
|
||||
field
|
||||
message
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
8
simple-payment-gateway/src/routes/manifest.rs
Normal file
8
simple-payment-gateway/src/routes/manifest.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use axum::{extract::State, Json};
|
||||
use saleor_app_sdk::{manifest::AppManifest};
|
||||
|
||||
use crate::app::{AppError, AppState};
|
||||
|
||||
pub async fn manifest(State(state): State<AppState>) -> Result<Json<AppManifest>, AppError> {
|
||||
Ok(Json(state.manifest))
|
||||
}
|
40
simple-payment-gateway/src/routes/mod.rs
Normal file
40
simple-payment-gateway/src/routes/mod.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use axum::{
|
||||
handler::HandlerWithoutStateExt,
|
||||
http::StatusCode,
|
||||
middleware,
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use saleor_app_sdk::middleware::verify_webhook_signature::webhook_signature_verifier;
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
use crate::app::AppState;
|
||||
|
||||
pub mod manifest;
|
||||
pub mod register;
|
||||
pub mod webhooks;
|
||||
use manifest::manifest;
|
||||
use register::register;
|
||||
use webhooks::webhooks;
|
||||
|
||||
pub fn create_routes(state: AppState) -> Router {
|
||||
async fn handle_404() -> (StatusCode, &'static str) {
|
||||
(StatusCode::NOT_FOUND, "Not found")
|
||||
}
|
||||
let service = handle_404.into_service();
|
||||
let serve_dir = ServeDir::new("saleor-app-template/public").not_found_service(service);
|
||||
|
||||
Router::new()
|
||||
.layer(middleware::from_fn(webhook_signature_verifier))
|
||||
//handles just path, eg. localhost:3000/
|
||||
.route("/api/webhooks", post(webhooks))
|
||||
.route(
|
||||
"/",
|
||||
get(|| async { "Your app got installed successfully!" }),
|
||||
)
|
||||
//handles files, eg. localhost:3000/logo.png
|
||||
.fallback_service(serve_dir)
|
||||
.route("/api/manifest", get(manifest))
|
||||
.route("/api/register", post(register))
|
||||
.with_state(state)
|
||||
}
|
40
simple-payment-gateway/src/routes/register.rs
Normal file
40
simple-payment-gateway/src/routes/register.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use anyhow::Context;
|
||||
use axum::{
|
||||
extract::Json,
|
||||
extract::State,
|
||||
http::{HeaderMap, StatusCode},
|
||||
};
|
||||
use saleor_app_sdk::{AuthData, AuthToken};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::app::{AppError, AppState};
|
||||
|
||||
pub async fn register(
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
Json(auth_token): Json<AuthToken>,
|
||||
) -> Result<StatusCode, AppError> {
|
||||
debug!(
|
||||
"/api/register:\nsaleor_api_url:{:?}\nauth_token:{:?}",
|
||||
headers.get("saleor-api-url"),
|
||||
auth_token
|
||||
);
|
||||
|
||||
if auth_token.auth_token.is_empty() {
|
||||
return Err(anyhow::anyhow!("missing auth_token").into());
|
||||
}
|
||||
let app = state.saleor_app.lock().await;
|
||||
let saleor_api_url = headers.get("saleor-api-url").context("missing api field")?;
|
||||
let saleor_api_url = saleor_api_url.to_str()?.to_owned();
|
||||
let auth_data = AuthData {
|
||||
jwks: None,
|
||||
token: auth_token.auth_token,
|
||||
domain: Some(state.config.app_api_base_url),
|
||||
app_id: state.manifest.id,
|
||||
saleor_api_url: saleor_api_url.clone(),
|
||||
};
|
||||
app.apl.set(auth_data).await?;
|
||||
|
||||
info!("registered app for{:?}", &saleor_api_url);
|
||||
Ok(StatusCode::OK)
|
||||
}
|
58
simple-payment-gateway/src/routes/webhooks.rs
Normal file
58
simple-payment-gateway/src/routes/webhooks.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use anyhow::Context;
|
||||
use axum::{
|
||||
extract::State,
|
||||
http::{HeaderMap, StatusCode},
|
||||
};
|
||||
use saleor_app_sdk::{
|
||||
headers::SALEOR_API_URL_HEADER,
|
||||
webhooks::{
|
||||
utils::{get_webhook_event_type, EitherWebhookType},
|
||||
SyncWebhookEventType,
|
||||
},
|
||||
};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::app::{AppError, AppState};
|
||||
|
||||
pub async fn webhooks(
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
body: String,
|
||||
) -> Result<StatusCode, AppError> {
|
||||
debug!("/api/webhooks");
|
||||
debug!("req: {:?}", body);
|
||||
debug!("headers: {:?}", headers);
|
||||
|
||||
let url = headers
|
||||
.get(SALEOR_API_URL_HEADER)
|
||||
.context("missing saleor api url header")?
|
||||
.to_str()?
|
||||
.to_owned();
|
||||
let event_type = get_webhook_event_type(&headers)?;
|
||||
match event_type {
|
||||
EitherWebhookType::Sync(a) => match a {
|
||||
SyncWebhookEventType::PaymentGatewayInitializeSession => {
|
||||
initialize_gateway(&state, &url).await?;
|
||||
}
|
||||
SyncWebhookEventType::TransactionProcessSession
|
||||
| SyncWebhookEventType::TransactionChargeRequested
|
||||
| SyncWebhookEventType::TransactionRefundRequested
|
||||
| SyncWebhookEventType::TransactionInitializeSession => {
|
||||
update_transaction_response(&state, &url).await?;
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
info!("got webhooks!");
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
async fn initialize_gateway(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn update_transaction_response(state: &AppState, saleor_api_url: &str) -> anyhow::Result<()> {
|
||||
todo!()
|
||||
}
|
|
@ -9,7 +9,7 @@ repository = "https://github.com/djkato/saleor-apps-rs"
|
|||
documentation = "https://github.com/djkato/saleor-apps-rs"
|
||||
keywords = ["saleor", "plugin"]
|
||||
categories = ["web-programming::http-server"]
|
||||
license = "PolyForm Noncommercial License 1.0.0"
|
||||
license = "PolyForm-Noncommercial-1.0.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 11 KiB |
Loading…
Reference in a new issue