#![allow(clippy::all, unused_imports, dead_code)]
use crate::{Actor, ActorBehavior, ClientBuilderExt, Message, Port};
use anyhow::{Error, Result};
use reflow_actor::{message::EncodableValue, ActorContext};
use reflow_actor_macro::actor;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::time::Duration;
const BASE_URL: &str = "https://api.sandbox.braintreegateway.com";
const ENV_KEY: &str = "BRAINTREE_API_KEY";
fn apply_auth(
config: &reflow_actor::ActorConfig,
mut builder: reqwest::RequestBuilder,
) -> Result<reqwest::RequestBuilder> {
let credential = config
.get_config_or_env(ENV_KEY)
.ok_or_else(|| anyhow::anyhow!("Missing env var: {}", ENV_KEY))?;
builder = builder.header("Authorization", format!("Basic {}", credential));
Ok(builder)
}
#[actor(
BraintreeCreateTransactionActor,
inports::<100>(merchant_id, amount),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_transaction(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/transactions".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("amount") {
body.insert("amount".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /merchants/{{merchant_id}}/transactions failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeCreateCustomerActor,
inports::<100>(merchant_id, id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_customer(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/customers".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("id") {
body.insert("id".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /merchants/{{merchant_id}}/customers failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeCreateClientTokenActor,
inports::<100>(merchant_id, version, customer_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_client_token(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/client_token".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("version") {
body.insert("version".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("customer_id") {
body.insert("customer_id".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /merchants/{{merchant_id}}/client_token failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeReadTransactionActor,
inports::<100>(merchant_id, transaction_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_read_transaction(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/transactions/{transaction_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("transaction_id") {
endpoint = endpoint.replace("{{transaction_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /merchants/{{merchant_id}}/transactions/{{transaction_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeCreateTransactionSettlementActor,
inports::<100>(merchant_id, transaction_id, amount),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_transaction_settlement(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint =
"/merchants/{merchant_id}/transactions/{transaction_id}/submit_for_settlement".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("transaction_id") {
endpoint = endpoint.replace("{{transaction_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("amount") {
body.insert("amount".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("PUT /merchants/{{merchant_id}}/transactions/{{transaction_id}}/submit_for_settlement failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeCreateTransactionRefundActor,
inports::<100>(merchant_id, transaction_id, amount),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_transaction_refund(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/transactions/{transaction_id}/refund".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("transaction_id") {
endpoint = endpoint.replace("{{transaction_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("amount") {
body.insert("amount".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("POST /merchants/{{merchant_id}}/transactions/{{transaction_id}}/refund failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeDeleteTransactionActor,
inports::<100>(merchant_id, transaction_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_delete_transaction(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/transactions/{transaction_id}/void".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("transaction_id") {
endpoint = endpoint.replace("{{transaction_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("PUT /merchants/{{merchant_id}}/transactions/{{transaction_id}}/void failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeSearchTransactionsActor,
inports::<100>(merchant_id, ids, amount, created_at, status, customer_email),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_search_transactions(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/transactions/advanced_search".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("ids") {
body.insert("ids".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("amount") {
body.insert("amount".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("created_at") {
body.insert("created_at".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("status") {
body.insert("status".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("customer_email") {
body.insert("customer_email".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /merchants/{{merchant_id}}/transactions/advanced_search failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeReadCustomerActor,
inports::<100>(merchant_id, customer_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_read_customer(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/customers/{customer_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("customer_id") {
endpoint = endpoint.replace("{{customer_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /merchants/{{merchant_id}}/customers/{{customer_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeUpdateCustomerActor,
inports::<100>(merchant_id, customer_id, first_name, last_name, email, phone),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_update_customer(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/customers/{customer_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("customer_id") {
endpoint = endpoint.replace("{{customer_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("first_name") {
body.insert("first_name".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("last_name") {
body.insert("last_name".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("phone") {
body.insert("phone".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"PUT /merchants/{{merchant_id}}/customers/{{customer_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeDeleteCustomerActor,
inports::<100>(merchant_id, customer_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_delete_customer(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/customers/{customer_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("customer_id") {
endpoint = endpoint.replace("{{customer_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"DELETE /merchants/{{merchant_id}}/customers/{{customer_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeCreatePaymentMethodActor,
inports::<100>(merchant_id, payment_method_nonce, customer_id, make_default, verification_merchant_account_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_payment_method(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/payment_methods".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("payment_method_nonce") {
body.insert("payment_method_nonce".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("customer_id") {
body.insert("customer_id".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("make_default") {
body.insert("make_default".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("verification_merchant_account_id") {
body.insert(
"verification_merchant_account_id".to_string(),
val.clone().into(),
);
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /merchants/{{merchant_id}}/payment_methods failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeReadPaymentMethodActor,
inports::<100>(merchant_id, payment_method_type, token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_read_payment_method(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint =
"/merchants/{merchant_id}/payment_methods/{payment_method_type}/{token}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("payment_method_type") {
endpoint = endpoint.replace("{{payment_method_type}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("token") {
endpoint = endpoint.replace("{{token}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("GET /merchants/{{merchant_id}}/payment_methods/{{payment_method_type}}/{{token}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeUpdatePaymentMethodActor,
inports::<100>(merchant_id, payment_method_type, token, make_default),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_update_payment_method(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint =
"/merchants/{merchant_id}/payment_methods/{payment_method_type}/{token}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("payment_method_type") {
endpoint = endpoint.replace("{{payment_method_type}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("token") {
endpoint = endpoint.replace("{{token}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("make_default") {
body.insert("make_default".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("PUT /merchants/{{merchant_id}}/payment_methods/{{payment_method_type}}/{{token}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeDeletePaymentMethodActor,
inports::<100>(merchant_id, payment_method_type, token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_delete_payment_method(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint =
"/merchants/{merchant_id}/payment_methods/{payment_method_type}/{token}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("payment_method_type") {
endpoint = endpoint.replace("{{payment_method_type}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("token") {
endpoint = endpoint.replace("{{token}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("DELETE /merchants/{{merchant_id}}/payment_methods/{{payment_method_type}}/{{token}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeCreateSubscriptionActor,
inports::<100>(merchant_id, payment_method_token, plan_id, price, first_billing_date, number_of_billing_cycles),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_subscription(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/subscriptions".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("payment_method_token") {
body.insert("payment_method_token".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("plan_id") {
body.insert("plan_id".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("price") {
body.insert("price".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("first_billing_date") {
body.insert("first_billing_date".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("number_of_billing_cycles") {
body.insert("number_of_billing_cycles".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /merchants/{{merchant_id}}/subscriptions failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeReadSubscriptionActor,
inports::<100>(merchant_id, subscription_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_read_subscription(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/subscriptions/{subscription_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("subscription_id") {
endpoint = endpoint.replace("{{subscription_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("GET /merchants/{{merchant_id}}/subscriptions/{{subscription_id}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeUpdateSubscriptionActor,
inports::<100>(merchant_id, subscription_id, plan_id, price, payment_method_token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_update_subscription(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/subscriptions/{subscription_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("subscription_id") {
endpoint = endpoint.replace("{{subscription_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("plan_id") {
body.insert("plan_id".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("price") {
body.insert("price".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("payment_method_token") {
body.insert("payment_method_token".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("PUT /merchants/{{merchant_id}}/subscriptions/{{subscription_id}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeDeleteSubscriptionActor,
inports::<100>(merchant_id, subscription_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_delete_subscription(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint =
"/merchants/{merchant_id}/subscriptions/{subscription_id}/cancel".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("subscription_id") {
endpoint = endpoint.replace("{{subscription_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("PUT /merchants/{{merchant_id}}/subscriptions/{{subscription_id}}/cancel failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeListPlansActor,
inports::<100>(merchant_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_list_plans(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/plans".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("GET /merchants/{{merchant_id}}/plans failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeListDisputesActor,
inports::<100>(merchant_id, received_date, status, kind),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_list_disputes(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/disputes/advanced_search".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("received_date") {
body.insert("received_date".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("status") {
body.insert("status".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("kind") {
body.insert("kind".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /merchants/{{merchant_id}}/disputes/advanced_search failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeReadDisputeActor,
inports::<100>(merchant_id, dispute_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_read_dispute(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/disputes/{dispute_id}".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("dispute_id") {
endpoint = endpoint.replace("{{dispute_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /merchants/{{merchant_id}}/disputes/{{dispute_id}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
BraintreeCreateDisputeEvidenceActor,
inports::<100>(merchant_id, dispute_id, comments, document_upload_id),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_dispute_evidence(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/disputes/{dispute_id}/evidence".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("dispute_id") {
endpoint = endpoint.replace("{{dispute_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("comments") {
body.insert("comments".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("document_upload_id") {
body.insert("document_upload_id".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("POST /merchants/{{merchant_id}}/disputes/{{dispute_id}}/evidence failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
BraintreeCreateWebhookActor,
inports::<100>(merchant_id, url, all_subscribed),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn braintree_create_webhook(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/merchants/{merchant_id}/webhooks".to_string();
if let Some(val) = inputs.get("merchant_id") {
endpoint = endpoint.replace("{{merchant_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout_compat(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("url") {
body.insert("url".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("all_subscribed") {
body.insert("all_subscribed".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /merchants/{{merchant_id}}/webhooks failed: {}", e).into(),
),
);
}
}
Ok(output)
}