-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from montdidier/feature/refunds
add refunds
- Loading branch information
Showing
7 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
mod currency; | ||
mod charge; | ||
mod card; | ||
mod refund; | ||
|
||
pub use currency::*; | ||
pub use charge::*; | ||
pub use card::*; | ||
pub use refund::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use time::{OffsetDateTime}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use crate::client::{Client, Response}; | ||
use crate::error::PinError; | ||
use crate::ids::{RefundId, ChargeId}; | ||
use crate::params::{Page, Paginator, unpack_contained, paginate}; | ||
use crate::resources::{ | ||
Currency | ||
}; | ||
use crate::build_map; | ||
|
||
#[derive(Clone, Debug, Serialize, Default)] | ||
pub struct CreateRefund { | ||
pub amount: Option<i64> | ||
} | ||
|
||
#[derive(Clone, Debug, Default, Deserialize)] | ||
pub struct Refund { | ||
pub token: RefundId, | ||
pub success: Option<bool>, | ||
pub amount: i64, | ||
pub currency: Currency, | ||
pub charge: ChargeId, | ||
#[serde(with = "time::serde::iso8601::option")] | ||
pub created_at: Option<OffsetDateTime>, | ||
pub error_message: Option<String>, | ||
pub status_message: String | ||
} | ||
|
||
impl Refund { | ||
pub fn create(client: &Client, token: &ChargeId, params: CreateRefund) -> Response<Refund> { | ||
unpack_contained(client.post_form(&format!("/charges/{}/refunds", token), ¶ms)) | ||
} | ||
|
||
pub fn list(client: &Client, page: Option<u32>, per_page: Option<u32>) -> Response<Page<Refund>> { | ||
let page = page.map(|s| s.to_string()); | ||
let per_page = per_page.map(|s| s.to_string()); | ||
let params = build_map([ | ||
("page", page.as_deref()), | ||
("per_page", per_page.as_deref()) | ||
]); | ||
client.get_query("/refunds", ¶ms) | ||
} | ||
|
||
pub fn list_with_paginator(client: &Client, per_page: Option<u32>) -> Paginator<Result<Refund, PinError>> { | ||
paginate( | ||
move |page, per_page| { | ||
Refund::list(client, Some(page), Some(per_page)) | ||
}, | ||
per_page.unwrap_or(25) | ||
) | ||
} | ||
|
||
pub fn list_for_charge(client: &Client, token: &ChargeId, page: Option<u32>, per_page: Option<u32>) -> Response<Page<Refund>> { | ||
let page = page.map(|s| s.to_string()); | ||
let per_page = per_page.map(|s| s.to_string()); | ||
let params = build_map([ | ||
("page", page.as_deref()), | ||
("per_page", per_page.as_deref()) | ||
]); | ||
client.get_query(&format!("/charges/{}/refunds", token), ¶ms) | ||
} | ||
|
||
pub fn list_for_charge_with_paginator<'a>(client: &'a Client, token: &'a ChargeId, per_page: Option<u32>) -> Paginator<'a, Result<Refund, PinError>> { | ||
paginate( | ||
move |page, per_page| { | ||
Refund::list_for_charge(client, token, Some(page), Some(per_page)) | ||
}, | ||
per_page.unwrap_or(25) | ||
) | ||
} | ||
|
||
pub fn retrieve(client: &Client, token: &RefundId) -> Response<Refund> { | ||
unpack_contained(client.get(&format!("/refunds/{}", token))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"response": { | ||
"token": "rf_ERCQy--Ay6o-NKGiUVcKKA", | ||
"success": null, | ||
"amount": 400, | ||
"currency": "USD", | ||
"charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA", | ||
"created_at": "2012-10-27T13:00:00Z", | ||
"error_message": null, | ||
"status_message": "Pending" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"response": [ | ||
{ | ||
"token": "rf_ERCQy--Ay6o-NKGiUVcKKA", | ||
"success": null, | ||
"amount": 400, | ||
"currency": "USD", | ||
"charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA", | ||
"created_at": "2012-10-27T13:00:00Z", | ||
"error_message": null, | ||
"status_message": "Pending" | ||
} | ||
], | ||
"count": 1, | ||
"pagination": { | ||
"current": 1, | ||
"previous": null, | ||
"next": null, | ||
"per_page": 25, | ||
"pages": 1, | ||
"count": 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"response": { | ||
"token": "rf_ERCQy--Ay6o-NKGiUVcKKA", | ||
"success": null, | ||
"amount": 400, | ||
"currency": "USD", | ||
"charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA", | ||
"created_at": "2012-10-27T13:00:00Z", | ||
"error_message": null, | ||
"status_message": "Pending" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"response": [ | ||
{ | ||
"token": "rf_ERCQy--Ay6o-NKGiUVcKKA", | ||
"success": null, | ||
"amount": 400, | ||
"currency": "USD", | ||
"charge": "ch_bZ3RhJnIUZ8HhfvH8CCvfA", | ||
"created_at": "2012-10-27T13:00:00Z", | ||
"error_message": null, | ||
"status_message": "Pending" | ||
} | ||
], | ||
"count": 1, | ||
"pagination": { | ||
"current": 1, | ||
"previous": null, | ||
"next": null, | ||
"per_page": 25, | ||
"pages": 1, | ||
"count": 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
use pinpayments::{Client, Currency, CreateRefund, Refund}; | ||
use std::fs::File; | ||
use httptest::{ServerPool, Expectation, matchers::*, responders::*}; | ||
use surf::http::auth::BasicAuth; | ||
use time::macros::datetime; | ||
|
||
static SERVER_POOL: ServerPool = ServerPool::new(2); | ||
|
||
fn get_fixture(path: &str) -> serde_json::Value { | ||
let file = File::open(path) | ||
.expect("file should open read only"); | ||
serde_json::from_reader(file).expect("file should be JSON") | ||
} | ||
|
||
#[tokio::test] | ||
async fn charge_refund_test() { | ||
let json = get_fixture("tests/fixtures/create-refund.json"); | ||
|
||
let auth = BasicAuth::new("sk_test_12345", ""); | ||
|
||
let server = SERVER_POOL.get_server(); | ||
|
||
let charge_token = "ch_bZ3RhJnIUZ8HhfvH8CCvfA".parse().unwrap(); | ||
|
||
server.expect( | ||
Expectation::matching( | ||
all_of![ | ||
request::method_path("POST", format!("/1/charges/{}/refunds", charge_token)), | ||
request::headers( | ||
contains((String::from(auth.name().as_str()), String::from(auth.value().as_str()))) | ||
), | ||
]). | ||
respond_with( | ||
status_code(201) | ||
.append_header("Content-Type", "application/json") | ||
.body(serde_json::to_string(&json).expect("failed to serialize body"))), | ||
); | ||
|
||
let client = Client::from_url(server.url_str("/1/").as_str(), "sk_test_12345"); | ||
|
||
let refund = Refund::create( | ||
&client, | ||
&charge_token, | ||
CreateRefund { | ||
amount: None | ||
} | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!(refund.token, "rf_ERCQy--Ay6o-NKGiUVcKKA"); | ||
} | ||
|
||
#[tokio::test] | ||
async fn refund_list_test() { | ||
let json = get_fixture("tests/fixtures/get-refunds.json"); | ||
|
||
let server = SERVER_POOL.get_server(); | ||
|
||
server.expect( | ||
Expectation::matching(request::method_path("GET", "/1/refunds")). | ||
respond_with(json_encoded(json)), | ||
); | ||
|
||
let client = Client::from_url(server.url_str("/1/").as_str(), "sk_test_12345"); | ||
let refunds = Refund::list(&client, None, None).await.unwrap(); | ||
|
||
assert_eq!(refunds.items[0].token, "rf_ERCQy--Ay6o-NKGiUVcKKA"); | ||
assert_eq!(refunds.items[0].success, None); | ||
assert_eq!(refunds.items[0].amount, 400); | ||
assert_eq!(refunds.items[0].currency, Currency::USD); | ||
assert_eq!(refunds.items[0].charge, "ch_bZ3RhJnIUZ8HhfvH8CCvfA"); | ||
assert_eq!(refunds.items[0].created_at.unwrap(), datetime!(2012-10-27 13:00 UTC)); | ||
assert_eq!(refunds.items[0].error_message, None); | ||
assert_eq!(refunds.items[0].status_message, "Pending"); | ||
} | ||
|
||
#[tokio::test] | ||
async fn charge_refunds_test() { | ||
let json = get_fixture("tests/fixtures/get-refunds.json"); | ||
|
||
let server = SERVER_POOL.get_server(); | ||
|
||
let charge_token = "ch_bZ3RhJnIUZ8HhfvH8CCvfA".parse().unwrap(); | ||
|
||
server.expect( | ||
Expectation::matching(request::method_path("GET", format!("/1/charges/{}/refunds", charge_token))). | ||
respond_with(json_encoded(json)), | ||
); | ||
|
||
let client = Client::from_url(server.url_str("/1/").as_str(), "sk_test_12345"); | ||
let refunds = Refund::list_for_charge(&client, &charge_token, None, None).await.unwrap(); | ||
|
||
assert_eq!(refunds.items[0].token, "rf_ERCQy--Ay6o-NKGiUVcKKA"); | ||
assert_eq!(refunds.items[0].success, None); | ||
assert_eq!(refunds.items[0].amount, 400); | ||
assert_eq!(refunds.items[0].currency, Currency::USD); | ||
assert_eq!(refunds.items[0].charge, "ch_bZ3RhJnIUZ8HhfvH8CCvfA"); | ||
assert_eq!(refunds.items[0].created_at.unwrap(), datetime!(2012-10-27 13:00 UTC)); | ||
assert_eq!(refunds.items[0].error_message, None); | ||
assert_eq!(refunds.items[0].status_message, "Pending"); | ||
} | ||
|
||
#[tokio::test] | ||
async fn get_refund_test() { | ||
let json = get_fixture("tests/fixtures/get-refund.json"); | ||
|
||
let server = SERVER_POOL.get_server(); | ||
|
||
let refund_token = "rf_ERCQy--Ay6o-NKGiUVcKKA".parse().unwrap(); | ||
|
||
server.expect( | ||
Expectation::matching(request::method_path("GET", format!("/1/refunds/{}", refund_token))). | ||
respond_with(json_encoded(json)), | ||
); | ||
|
||
let client = Client::from_url(server.url_str("/1/").as_str(), "sk_test_12345"); | ||
let refund = Refund::retrieve(&client, &refund_token).await.unwrap(); | ||
|
||
assert_eq!(refund.token, "rf_ERCQy--Ay6o-NKGiUVcKKA"); | ||
assert_eq!(refund.success, None); | ||
assert_eq!(refund.amount, 400); | ||
assert_eq!(refund.currency, Currency::USD); | ||
assert_eq!(refund.charge, "ch_bZ3RhJnIUZ8HhfvH8CCvfA"); | ||
assert_eq!(refund.created_at.unwrap(), datetime!(2012-10-27 13:00 UTC)); | ||
assert_eq!(refund.error_message, None); | ||
assert_eq!(refund.status_message, "Pending"); | ||
} |