Add many additional create order fields
This commit is contained in:
parent
9658abe3b8
commit
94e7e7eb1e
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2135,7 +2135,7 @@ checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pay_u"
|
name = "pay_u"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
|
@ -153,8 +153,12 @@ pub(crate) async fn request_payment(
|
|||||||
client
|
client
|
||||||
.lock()
|
.lock()
|
||||||
.create_order(
|
.create_order(
|
||||||
OrderCreateRequest::new(msg.buyer.into(), msg.customer_ip, msg.currency)
|
OrderCreateRequest::build(
|
||||||
.with_description(msg.description)
|
msg.buyer.into(),
|
||||||
|
msg.customer_ip,
|
||||||
|
msg.currency,
|
||||||
|
msg.description,
|
||||||
|
)?
|
||||||
.with_notify_url(msg.redirect_uri)
|
.with_notify_url(msg.redirect_uri)
|
||||||
.with_products(msg.products.into_iter().map(Into::into)),
|
.with_products(msg.products.into_iter().map(Into::into)),
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pay_u"
|
name = "pay_u"
|
||||||
description = "PayU Rest API wrapper"
|
description = "PayU Rest API wrapper"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -17,11 +17,13 @@ async fn usage() {
|
|||||||
client.authorize().await.expect("Invalid credentials");
|
client.authorize().await.expect("Invalid credentials");
|
||||||
|
|
||||||
let _res = client.create_order(
|
let _res = client.create_order(
|
||||||
OrderCreateRequest::new(
|
OrderCreateRequest::build(
|
||||||
Buyer::new("john.doe@example.com", "654111654", "John", "Doe", "pl"),
|
Buyer::new("john.doe@example.com", "654111654", "John", "Doe", "pl"),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"PLN",
|
"PLN",
|
||||||
|
"Some description"
|
||||||
)
|
)
|
||||||
|
.expect("All required fields must be valid")
|
||||||
// Endpoint which will be requested by PayU with payment status update
|
// Endpoint which will be requested by PayU with payment status update
|
||||||
.with_notify_url("https://your.eshop.com/notify")
|
.with_notify_url("https://your.eshop.com/notify")
|
||||||
// payment description (MANDATORY)
|
// payment description (MANDATORY)
|
||||||
@ -94,6 +96,10 @@ async fn handle_notification(path: Path<i32>, Json(notify): Json<pay_u::notify::
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Releases
|
||||||
|
|
||||||
|
0.1.7 - Added credit and more create order request options like additional description, visible description.
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
Please report bugs here: https://todo.sr.ht/~tsumanu/payu-rs
|
Please report bugs here: https://todo.sr.ht/~tsumanu/payu-rs
|
||||||
|
439
pay_u/src/lib.rs
439
pay_u/src/lib.rs
@ -198,19 +198,86 @@ pub enum RefundStatus {
|
|||||||
Completed,
|
Completed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Delivery {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Street name
|
||||||
|
street: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Postal box number
|
||||||
|
postal_box: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Postal code
|
||||||
|
postal_code: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// City
|
||||||
|
city: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Province
|
||||||
|
state: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Two-letter country code compliant with ISO-3166.
|
||||||
|
country_code: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Address description
|
||||||
|
name: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Recipient’s name
|
||||||
|
recipient_name: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Recipient’s e-mail address
|
||||||
|
recipient_email: Option<String>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// Recipient’s phone number
|
||||||
|
recipient_phone: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct BuyerShippingAddress {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
/// stores the shipping address
|
||||||
|
delivery: Option<Delivery>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuyerShippingAddress {
|
||||||
|
pub fn new_with_delivery(delivery: Delivery) -> Self {
|
||||||
|
Self {
|
||||||
|
delivery: Some(delivery),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Buyer {
|
pub struct Buyer {
|
||||||
/// Required customer e-mail
|
/// Required customer e-mail
|
||||||
email: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
email: Option<String>,
|
||||||
/// Required customer phone number
|
/// Required customer phone number
|
||||||
phone: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
phone: Option<String>,
|
||||||
/// Required customer first name
|
/// Required customer first name
|
||||||
first_name: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
first_name: Option<String>,
|
||||||
/// Required customer last name
|
/// Required customer last name
|
||||||
last_name: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
last_name: Option<String>,
|
||||||
/// Required customer language
|
/// Required customer language
|
||||||
language: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
language: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
delivery: Option<BuyerShippingAddress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buyer {
|
impl Buyer {
|
||||||
@ -229,62 +296,68 @@ impl Buyer {
|
|||||||
Language: Into<String>,
|
Language: Into<String>,
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
email: email.into(),
|
email: Some(email.into()),
|
||||||
phone: phone.into(),
|
phone: Some(phone.into()),
|
||||||
first_name: first_name.into(),
|
first_name: Some(first_name.into()),
|
||||||
last_name: last_name.into(),
|
last_name: Some(last_name.into()),
|
||||||
language: lang.into(),
|
language: Some(lang.into()),
|
||||||
|
delivery: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn email(&self) -> &str {
|
pub fn email(&self) -> &str {
|
||||||
&self.email
|
self.email.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
pub fn with_email<S>(mut self, email: S) -> Self
|
pub fn with_email<S>(mut self, email: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.email = email.into();
|
self.email = Some(email.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn phone(&self) -> &str {
|
pub fn phone(&self) -> &str {
|
||||||
&self.phone
|
self.phone.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
pub fn with_phone<S>(mut self, phone: S) -> Self
|
pub fn with_phone<S>(mut self, phone: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.phone = phone.into();
|
self.phone = Some(phone.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn first_name(&self) -> &str {
|
pub fn first_name(&self) -> &str {
|
||||||
&self.first_name
|
self.first_name.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
pub fn with_first_name<S>(mut self, first_name: S) -> Self
|
pub fn with_first_name<S>(mut self, first_name: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.first_name = first_name.into();
|
self.first_name = Some(first_name.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn last_name(&self) -> &str {
|
pub fn last_name(&self) -> &str {
|
||||||
&self.last_name
|
self.last_name.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
pub fn with_last_name<S>(mut self, last_name: S) -> Self
|
pub fn with_last_name<S>(mut self, last_name: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.last_name = last_name.into();
|
self.last_name = Some(last_name.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn language(&self) -> &str {
|
pub fn language(&self) -> &str {
|
||||||
&self.language
|
self.language.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
pub fn with_language<S>(mut self, language: S) -> Self
|
pub fn with_language<S>(mut self, language: S) -> Self
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.language = language.into();
|
self.language = Some(language.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_delivery(mut self, delivery: Delivery) -> Self {
|
||||||
|
self.delivery = Some(BuyerShippingAddress::new_with_delivery(delivery));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,6 +379,14 @@ pub struct Product {
|
|||||||
deserialize_with = "deserialize::deserialize_u32"
|
deserialize_with = "deserialize::deserialize_u32"
|
||||||
)]
|
)]
|
||||||
pub quantity: Quantity,
|
pub quantity: Quantity,
|
||||||
|
/// Product type, which can be virtual or material; (possible values true or
|
||||||
|
/// false).
|
||||||
|
#[serde(rename = "virtual", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub virtual_product: Option<bool>,
|
||||||
|
/// Marketplace date from which the product (or offer) is available, ISO
|
||||||
|
/// format applies, e.g. "2019-03-27T10:57:59.000+01:00".
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub listing_date: Option<chrono::NaiveDateTime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Product {
|
impl Product {
|
||||||
@ -314,8 +395,238 @@ impl Product {
|
|||||||
name: name.into(),
|
name: name.into(),
|
||||||
unit_price,
|
unit_price,
|
||||||
quantity,
|
quantity,
|
||||||
|
virtual_product: None,
|
||||||
|
listing_date: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Product type, which can be virtual or material; (possible values true or
|
||||||
|
/// false).
|
||||||
|
pub fn into_virtual(mut self) -> Self {
|
||||||
|
self.virtual_product = Some(true);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Product type, which can be virtual or material; (possible values true or
|
||||||
|
/// false).
|
||||||
|
pub fn non_virtual(mut self) -> Self {
|
||||||
|
self.virtual_product = Some(false);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marketplace date from which the product (or offer) is available, ISO
|
||||||
|
/// format applies, e.g. "2019-03-27T10:57:59.000+01:00".
|
||||||
|
pub fn with_listing_date(mut self, listing_date: chrono::NaiveDateTime) -> Self {
|
||||||
|
self.listing_date = Some(listing_date);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn erase_listing_date(mut self) -> Self {
|
||||||
|
self.listing_date = None;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ShoppingCart {
|
||||||
|
/// Section containing data of shipping method.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
shopping_method: Option<ShoppingMethod>,
|
||||||
|
/// Section containing data about ordered products.
|
||||||
|
/// > Note: product objects in the <shoppingCart.products> section do not
|
||||||
|
/// > have a listingDate field
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
products: Option<Vec<Product>>,
|
||||||
|
/// Submerchant identifier. This field should be consistent with field
|
||||||
|
/// extCustomerId in shoppingCarts section when order is placed in
|
||||||
|
/// marketplace.
|
||||||
|
ext_customer_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShoppingCart {
|
||||||
|
pub fn new<ExtCustomerId, Products>(ext_customer_id: ExtCustomerId) -> Self
|
||||||
|
where
|
||||||
|
ExtCustomerId: Into<String>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
shopping_method: None,
|
||||||
|
ext_customer_id: ext_customer_id.into(),
|
||||||
|
products: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_products<ExtCustomerId, Products>(
|
||||||
|
ext_customer_id: ExtCustomerId,
|
||||||
|
products: Products,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
ExtCustomerId: Into<String>,
|
||||||
|
Products: Iterator<Item = Product>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
shopping_method: None,
|
||||||
|
ext_customer_id: ext_customer_id.into(),
|
||||||
|
products: Some(products.map(Product::erase_listing_date).collect()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_products<Products>(mut self, products: Products) -> Self
|
||||||
|
where
|
||||||
|
Products: Iterator<Item = Product>,
|
||||||
|
{
|
||||||
|
self.products = Some(products.map(Product::erase_listing_date).collect());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Section containing data of shipping method.
|
||||||
|
pub fn shopping_method(&self) -> &Option<ShoppingMethod> {
|
||||||
|
&self.shopping_method
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Section containing data about ordered products.
|
||||||
|
/// > Note: product objects in the <shoppingCart.products> section do not
|
||||||
|
/// > have a listingDate field
|
||||||
|
pub fn products(&self) -> &Option<Vec<Product>> {
|
||||||
|
&self.products
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Submerchant identifier. This field should be consistent with field
|
||||||
|
/// extCustomerId in shoppingCarts section when order is placed in
|
||||||
|
/// marketplace.
|
||||||
|
pub fn ext_customer_id(&self) -> &String {
|
||||||
|
&self.ext_customer_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type of shipment
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum ShoppingMethodType {
|
||||||
|
Courier,
|
||||||
|
CollectionPointPickup,
|
||||||
|
ParcelLocker,
|
||||||
|
StorePickup,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Address {
|
||||||
|
/// The full name of the pickup point, including its unique identifier, e.g.
|
||||||
|
/// „Parcel locker POZ29A”.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub point_id: Option<String>,
|
||||||
|
/// Street name, possibly including house and flat number.
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub street: Option<String>,
|
||||||
|
/// Street number
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub street_no: Option<String>,
|
||||||
|
/// Flat number
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub flat_no: Option<String>,
|
||||||
|
/// Postal code
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub postal_code: Option<String>,
|
||||||
|
/// City
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub city: Option<String>,
|
||||||
|
/// Two-letter country code compliant with ISO-3166
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub country_code: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ShoppingMethod {
|
||||||
|
/// Shipping type
|
||||||
|
/// Recommended
|
||||||
|
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub shopping_type: Option<ShoppingMethodType>,
|
||||||
|
/// Shipping cost
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub price: Option<String>,
|
||||||
|
/// Section containing data about shipping address.
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub address: Option<Address>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ApplicantAdditionalInfo {
|
||||||
|
/// Information whether there were previous, successfully completed orders
|
||||||
|
/// for applicant.
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
has_successfully_finished_order_in_shop: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Applicant {
|
||||||
|
/// Applicant’s email address
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
email: Option<String>,
|
||||||
|
/// Applicant’s phone number
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
phone: Option<String>,
|
||||||
|
/// Applicant’s first name
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
first_name: Option<String>,
|
||||||
|
/// Applicant’s last name
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
last_name: Option<String>,
|
||||||
|
/// Language code, ISO-639-1 compliant. Denotes the language version of
|
||||||
|
/// PayU hosted payment page and of e-mail messages sent from PayU to the
|
||||||
|
/// payer (supported values are here).
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
language: Option<String>,
|
||||||
|
/// National Identification Number
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
nin: Option<String>,
|
||||||
|
/// Section containing data about applicant’s address.
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
address: Option<Address>,
|
||||||
|
/// Additional information about person applying for credit.
|
||||||
|
/// Recommended
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
additional_info: Option<ApplicantAdditionalInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Credit {
|
||||||
|
/// Section containing data of the ordered products
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
shopping_carts: Option<Vec<ShoppingCart>>,
|
||||||
|
/// Section containing data of person applying for a credit
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
applicant: Option<Applicant>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Credit {
|
||||||
|
pub fn with_shopping_carts<ShoppingCarts>(mut self, shopping_carts: ShoppingCarts) -> Self
|
||||||
|
where
|
||||||
|
ShoppingCarts: Iterator<Item = ShoppingCart>,
|
||||||
|
{
|
||||||
|
self.shopping_carts = Some(shopping_carts.collect());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MultiUseCartToken
|
/// MultiUseCartToken
|
||||||
@ -504,9 +815,12 @@ pub struct OrderCreateRequest {
|
|||||||
/// number etc) visible on card statement (max. 22 chars). The name should
|
/// number etc) visible on card statement (max. 22 chars). The name should
|
||||||
/// be easy to recognize by the cardholder (e.g "shop.com 124343"). If field
|
/// be easy to recognize by the cardholder (e.g "shop.com 124343"). If field
|
||||||
/// is not provided, static name configured by PayU will be used.
|
/// is not provided, static name configured by PayU will be used.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
statement_description: Option<String>,
|
statement_description: Option<String>,
|
||||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||||
muct: Option<muct::MultiUseCartToken>,
|
muct: Option<muct::MultiUseCartToken>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
credit: Option<Credit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrderCreateRequest {
|
impl OrderCreateRequest {
|
||||||
@ -542,6 +856,7 @@ impl OrderCreateRequest {
|
|||||||
visible_description: None,
|
visible_description: None,
|
||||||
statement_description: None,
|
statement_description: None,
|
||||||
muct: None,
|
muct: None,
|
||||||
|
credit: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,26 +875,6 @@ impl OrderCreateRequest {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional description of the order.
|
|
||||||
pub fn with_additional_description<S: Into<String>>(
|
|
||||||
mut self,
|
|
||||||
additional_description: S,
|
|
||||||
) -> Self {
|
|
||||||
self.additional_description = Some(additional_description.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Text visible on the PayU payment page (max. 80 chars).
|
|
||||||
pub fn with_visible_description(mut self, visible_description: &str) -> Self {
|
|
||||||
let visible_description = if visible_description.len() > 60 {
|
|
||||||
&visible_description[..60]
|
|
||||||
} else {
|
|
||||||
visible_description
|
|
||||||
};
|
|
||||||
self.visible_description = Some(String::from(visible_description));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_multi_use_token(
|
pub fn with_multi_use_token(
|
||||||
mut self,
|
mut self,
|
||||||
recurring: muct::Recurring,
|
recurring: muct::Recurring,
|
||||||
@ -613,6 +908,9 @@ impl OrderCreateRequest {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of the an order.
|
||||||
|
///
|
||||||
|
/// > This method will override initial description!
|
||||||
pub fn with_description<Description>(mut self, desc: Description) -> Self
|
pub fn with_description<Description>(mut self, desc: Description) -> Self
|
||||||
where
|
where
|
||||||
Description: Into<String>,
|
Description: Into<String>,
|
||||||
@ -621,6 +919,38 @@ impl OrderCreateRequest {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Additional description of the order.
|
||||||
|
pub fn with_additional_description<S: Into<String>>(
|
||||||
|
mut self,
|
||||||
|
additional_description: S,
|
||||||
|
) -> Self {
|
||||||
|
self.additional_description = Some(additional_description.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Text visible on the PayU payment page (max. 80 chars).
|
||||||
|
pub fn with_visible_description(mut self, visible_description: &str) -> Self {
|
||||||
|
let visible_description = if visible_description.len() > 60 {
|
||||||
|
&visible_description[..60]
|
||||||
|
} else {
|
||||||
|
visible_description
|
||||||
|
};
|
||||||
|
self.visible_description = Some(String::from(visible_description));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Payment recipient name followed by payment description (order ID, ticket
|
||||||
|
/// number etc) visible on card statement (max. 22 chars). The name should
|
||||||
|
/// be easy to recognize by the cardholder (e.g "shop.com 124343"). If field
|
||||||
|
/// is not provided, static name configured by PayU will be used.
|
||||||
|
pub fn with_statement_description<Description>(mut self, desc: Description) -> Self
|
||||||
|
where
|
||||||
|
Description: Into<String>,
|
||||||
|
{
|
||||||
|
self.statement_description = Some(String::from(desc.into().trim()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Add url to which PayU will be able to send http request with payment
|
/// Add url to which PayU will be able to send http request with payment
|
||||||
/// status updates
|
/// status updates
|
||||||
///
|
///
|
||||||
@ -635,6 +965,28 @@ impl OrderCreateRequest {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Address for redirecting the customer after payment is commenced. If the
|
||||||
|
/// payment has not been authorized, error=501 parameter will be added.
|
||||||
|
/// Please note that no decision regarding payment status should be made
|
||||||
|
/// depending on the presence or lack of this parameter (to get payment
|
||||||
|
/// status, wait for notification or retrieve order details).
|
||||||
|
pub fn with_continue_url<ContinueUrl>(mut self, continue_url: ContinueUrl) -> Self
|
||||||
|
where
|
||||||
|
ContinueUrl: Into<String>,
|
||||||
|
{
|
||||||
|
self.continue_url = Some(continue_url.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Section containing credit data. This information is not required, but it
|
||||||
|
/// is strongly recommended to include it. Otherwise the buyer will be
|
||||||
|
/// prompted to provide missing data on provider page when payment by
|
||||||
|
/// Installments or Pay later.
|
||||||
|
pub fn with_credit(mut self, credit: Credit) -> Self {
|
||||||
|
self.credit = Some(credit);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// URL to which web hook will be send. It's important to return 200 to all
|
/// URL to which web hook will be send. It's important to return 200 to all
|
||||||
/// notifications.
|
/// notifications.
|
||||||
///
|
///
|
||||||
@ -675,25 +1027,30 @@ impl OrderCreateRequest {
|
|||||||
&self.customer_ip
|
&self.customer_ip
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn merchant_pos_id(&self) -> MerchantPosId {
|
pub fn merchant_pos_id(&self) -> MerchantPosId {
|
||||||
self.merchant_pos_id
|
self.merchant_pos_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn description(&self) -> &String {
|
pub fn description(&self) -> &String {
|
||||||
&self.description
|
&self.description
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn currency_code(&self) -> &String {
|
pub fn currency_code(&self) -> &String {
|
||||||
&self.currency_code
|
&self.currency_code
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn total_amount(&self) -> &Price {
|
pub fn total_amount(&self) -> &Price {
|
||||||
&self.total_amount
|
&self.total_amount
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buyer(&self) -> &Option<Buyer> {
|
pub fn buyer(&self) -> &Option<Buyer> {
|
||||||
&self.buyer
|
&self.buyer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn products(&self) -> &[Product] {
|
pub fn products(&self) -> &[Product] {
|
||||||
&self.products
|
&self.products
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn order_create_date(&self) -> &Option<String> {
|
pub fn order_create_date(&self) -> &Option<String> {
|
||||||
&self.order_create_date
|
&self.order_create_date
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user