use reqwest::{Method, RequestBuilder};
use serde::{Deserialize, Serialize};
use crate::{ApiRequest, PixClient};
pub struct CobEndpoint<'a> {
inner: &'a PixClient,
}
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub enum CobrancaStatus {
ATIVA,
CONCLUIDA,
REMOVIDA_PELO_USUARIO_RECEBEDOR,
REMOVIDA_PELO_PSP,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CobrancaImediata {
pub calendario: Calendario,
pub devedor: Devedor,
pub valor: Valor,
#[serde(rename = "chave")]
pub chave_pix_recebedor: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub txid: Option<String>,
#[serde(rename = "loc")]
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<Location>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(rename = "solicitacaoPagador")]
#[serde(skip_serializing_if = "Option::is_none")]
pub solicitacao_pagador: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "infoAdicionais")]
pub info_adicionais: Option<Vec<InfoAdicionais>>,
}
impl CobrancaImediata {
pub fn new(valor: f64, chave_pix_recebedor: String, devedor: Devedor) -> CobrancaImediata {
let valor = Valor::new(valor, false);
Self {
calendario: Default::default(),
devedor,
valor,
chave_pix_recebedor,
txid: None,
location: None,
status: None,
solicitacao_pagador: None,
info_adicionais: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Calendario {
#[serde(skip_serializing_if = "Option::is_none")]
pub criacao: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub apresentacao: Option<String>,
pub expiracao: i64,
}
impl Default for Calendario {
fn default() -> Self {
Self {
criacao: None,
apresentacao: None,
expiracao: 3600,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Devedor {
#[serde(skip_serializing_if = "Option::is_none")]
cnpj: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
cpf: Option<String>,
nome: String,
}
impl Devedor {
pub fn new_pessoa_juridica(cnpj: String, nome: String) -> Self {
Self {
cnpj: Some(cnpj),
cpf: None,
nome,
}
}
pub fn new_pessoa_fisica(cpf: String, nome: String) -> Self {
Self {
cnpj: None,
cpf: Some(cpf),
nome,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Valor {
pub original: String,
#[serde(rename = "modalidadeAlteracao")]
#[serde(skip_serializing_if = "Option::is_none")]
pub permite_alteracao: Option<i32>,
}
impl Valor {
pub fn new(valor_original: f64, permite_alteracao: bool) -> Valor {
let permite_alteracao = if permite_alteracao { Some(1) } else { None };
Self {
original: format!("{:.2}", valor_original),
permite_alteracao,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Location {
id: i64,
#[serde(rename = "location")]
pub url: String,
#[serde(rename = "tipoCob")]
tipo_cob: String,
criacao: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct InfoAdicionais {
pub nome: String,
pub valor: String,
}
impl PixClient {
pub fn cob(&self) -> CobEndpoint {
CobEndpoint { inner: self }
}
}
impl<'a> CobEndpoint<'a> {
pub fn criar_cobranca_txid(&self, txid: String, payload: CobrancaImediata) -> ApiRequest<CobrancaImediata> {
let endpoint = format!("{}/cob/{}", &*self.inner.base_endpoint, txid);
self.inner.request_with_headers(Method::PUT, &*endpoint, payload)
}
pub fn consultar_cobranca_txid(&self, txid: String, payload: CobrancaImediata) -> ApiRequest<CobrancaImediata> {
let endpoint = format!("{}/cob/{}", &*self.inner.base_endpoint, txid);
self.inner.request_with_headers(Method::GET, &*endpoint, payload)
}
pub fn revisar_cobranca_txid(&self, txid: String, payload: CobrancaImediata) -> ApiRequest<CobrancaImediata> {
let endpoint = format!("{}/cob/{}", &*self.inner.base_endpoint, txid);
self.inner.request_with_headers(Method::POST, &*endpoint, payload)
}
pub fn criar_cobranca_imediata(&self, payload: CobrancaImediata) -> ApiRequest<CobrancaImediata> {
let endpoint = format!("{}/cob", &*self.inner.base_endpoint);
self.inner.request_with_headers(Method::POST, &*endpoint, payload)
}
pub fn consultar_cobrancas(&self) -> RequestBuilder {
let endpoint = format!("{}/cob", &*self.inner.base_endpoint);
self.inner.inner_client.request(Method::GET, &endpoint)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn t_value() {
let new_value = Valor::new(512.614, false);
println!(": {:?}", new_value);
let new_integer_value = Valor::new(400f64, false);
println!(": {:?}", new_integer_value);
}
}