Start update status
This commit is contained in:
parent
9b61b79483
commit
079212bed1
@ -27,5 +27,6 @@ pub fn wapc_init() {
|
|||||||
wapc::register_function("teardown", teardown);
|
wapc::register_function("teardown", teardown);
|
||||||
wapc::register_function("create_payment", create_payment);
|
wapc::register_function("create_payment", create_payment);
|
||||||
wapc::register_function("cancel_order", cancel_order);
|
wapc::register_function("cancel_order", cancel_order);
|
||||||
|
wapc::register_function("update_status", update_status);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -9,6 +9,8 @@ pub const CONFIG_POS: u32 = 3;
|
|||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("Malformed create payment message")]
|
#[error("Malformed create payment message")]
|
||||||
MalformedCreatePayment,
|
MalformedCreatePayment,
|
||||||
|
#[error("Malformed payment status update message")]
|
||||||
|
MalformedStatusUpdate,
|
||||||
#[error("Malformed authorize response")]
|
#[error("Malformed authorize response")]
|
||||||
MalformedAuthorize,
|
MalformedAuthorize,
|
||||||
#[error("Message pack: malformed create payment message")]
|
#[error("Message pack: malformed create payment message")]
|
||||||
@ -84,6 +86,16 @@ pub struct OrderCreated {
|
|||||||
pub redirect_uri: Option<String>,
|
pub redirect_uri: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct UpdateStatus {
|
||||||
|
pub payload: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct StatusUpdated {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum HttpMethod {
|
pub enum HttpMethod {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod credit;
|
mod credit;
|
||||||
mod deserialize;
|
mod deserialize;
|
||||||
mod model;
|
mod model;
|
||||||
|
mod notify;
|
||||||
mod req;
|
mod req;
|
||||||
mod res;
|
mod res;
|
||||||
mod serialize;
|
mod serialize;
|
||||||
@ -66,6 +67,7 @@ impl PayU {
|
|||||||
wapc::register_function("init", Self::init);
|
wapc::register_function("init", Self::init);
|
||||||
wapc::register_function("create_payment", Self::create_payment);
|
wapc::register_function("create_payment", Self::create_payment);
|
||||||
wapc::register_function("cancel_order", Self::cancel_order);
|
wapc::register_function("cancel_order", Self::cancel_order);
|
||||||
|
wapc::register_function("update_status", Self::update_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(_msg: &[u8]) -> wapc::CallResult {
|
fn teardown(_msg: &[u8]) -> wapc::CallResult {
|
||||||
@ -95,9 +97,9 @@ impl PayU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_payment(msg: &[u8]) -> wapc::CallResult {
|
fn create_payment(msg: &[u8]) -> wapc::CallResult {
|
||||||
let c: CreatePayment = match deserialize(msg) {
|
let c: CreatePayment = match wapc_codec::messagepack::deserialize(msg) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
_ => return Err(Box::new(Error::MalformedCreatePayment)),
|
_ => return Err(Box::new(Error::MsgPackDeserializationFailed)),
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("{:?}", c);
|
info!("{:?}", c);
|
||||||
@ -118,6 +120,24 @@ impl PayU {
|
|||||||
fn cancel_order(_msg: &[u8]) -> wapc::CallResult {
|
fn cancel_order(_msg: &[u8]) -> wapc::CallResult {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_status(msg: &[u8]) -> wapc::CallResult {
|
||||||
|
let update: UpdateStatus = match wapc_codec::messagepack::deserialize(msg) {
|
||||||
|
Ok(c) => c,
|
||||||
|
_ => return Err(Box::new(Error::MsgPackDeserializationFailed)),
|
||||||
|
};
|
||||||
|
let msg: notify::StatusUpdate = match serde_json::from_slice(&update.payload) {
|
||||||
|
Ok(msg) => msg,
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
return Err(Box::new(Error::MalformedStatusUpdate));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _status = msg.order.status;
|
||||||
|
let _xid = msg.order.ext_order_id;
|
||||||
|
|
||||||
|
Ok(wapc_codec::messagepack::serialize(StatusUpdated {}).unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_header() -> Vec<(String, String)> {
|
fn json_header() -> Vec<(String, String)> {
|
||||||
|
@ -120,14 +120,14 @@ pub enum CodeLiteral {
|
|||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Prop {
|
pub struct Prop {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Refund {
|
pub struct Refund {
|
||||||
pub refund_id: String,
|
pub refund_id: String,
|
||||||
|
162
crates/payment_adapter_pay_u/src/notify.rs
Normal file
162
crates/payment_adapter_pay_u/src/notify.rs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
//! Notification objects. Those objects will be send on notify_url if was given.
|
||||||
|
//!
|
||||||
|
//! To enable notifications for a specific payment, specify the notifyUrl
|
||||||
|
//! parameter in the payment form. Each payment can receive a different URL to
|
||||||
|
//! which notifications will be sent.
|
||||||
|
//!
|
||||||
|
//! Every notification is sent asynchronously. After your system receives a
|
||||||
|
//! notification with the status COMPLETED, instruct it to ignore any further
|
||||||
|
//! notifications.
|
||||||
|
//!
|
||||||
|
//! After sending a notification, PayU system requires a 200 HTTP status code in
|
||||||
|
//! response. If it receives a different status code, it will resend the
|
||||||
|
//! notification. Your system should also take account of situations where a
|
||||||
|
//! notification is sent several times with the same status. For each repeated
|
||||||
|
//! notification, response with code 200 should be sent as well.
|
||||||
|
//!
|
||||||
|
//! To ensure trusted communication between PayU and your shop, you must verify
|
||||||
|
//! the signature value available in the OpenPayu-Signature header each time
|
||||||
|
//! your system receives any notification from a PayU server. Refer to the
|
||||||
|
//! Verification of notifications signature for more information.
|
||||||
|
//!
|
||||||
|
//! Notifications are sent for orders in the following statuses: PENDING,
|
||||||
|
//! WAITING_FOR_CONFIRMATION, COMPLETED, CANCELED.
|
||||||
|
//!
|
||||||
|
//! Note: if you filter IP addresses, remember to allow IPs used by PayU to send
|
||||||
|
//! the notifications. These are:
|
||||||
|
//!
|
||||||
|
//! ### PRODUCTION
|
||||||
|
//!
|
||||||
|
//! > 185.68.12.10, 185.68.12.11, 185.68.12.12, 185.68.12.26, 185.68.12.27,
|
||||||
|
//! > 185.68.12.28
|
||||||
|
//!
|
||||||
|
//! ### SANDBOX
|
||||||
|
//!
|
||||||
|
//! > 185.68.14.10, 185.68.14.11, 185.68.14.12, 185.68.14.26, 185.68.14.27,
|
||||||
|
//! > 185.68.14.28
|
||||||
|
//!
|
||||||
|
//! ## Payment lifecycle
|
||||||
|
//!
|
||||||
|
//! You can configure a separate auto-receive / automatic collection parameter
|
||||||
|
//! for each payment method via the Management Panel.
|
||||||
|
//!
|
||||||
|
//! By default, auto-receive is enabled. The basic payment sequence is as
|
||||||
|
//! follows:
|
||||||
|
//!
|
||||||
|
//! 1) Each successfully authorized payment for an order is captured.
|
||||||
|
//! 2) The buyer is charged with the order amount.
|
||||||
|
//! 3) The shop balance is increased by the order amount.
|
||||||
|
//! 4) PayU calculates its commission to the order.
|
||||||
|
//!
|
||||||
|
//! If the auto-receive is turned off, you should capture each order using a PUT
|
||||||
|
//! method (Order capture) or cancel using DELETE method (Cancellation).
|
||||||
|
//!
|
||||||
|
//! If no such action is taken the order is auto-canceled. Automatic
|
||||||
|
//! cancellation occurs after a number of days indicated for the payment method.
|
||||||
|
//!
|
||||||
|
//! <img src="https://developers.payu.com/images/order_statusesV2-en.png" />
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::deserialize;
|
||||||
|
use crate::req::*;
|
||||||
|
use crate::OrderId;
|
||||||
|
|
||||||
|
/// Payment notification object received on notify_url
|
||||||
|
///
|
||||||
|
/// See [crate::req::CreateOrder::notify_url]
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct StatusUpdate {
|
||||||
|
/// Section containing order object
|
||||||
|
pub order: Order,
|
||||||
|
/// Moment of accepting the transaction and adding funds from the
|
||||||
|
/// transaction to the Shop balance. Format: "%Y-%M-%DT%h:%m:%s%z."
|
||||||
|
/// Example: "2020-06-09T17:52:04.644+02:00". If the millisecond counter
|
||||||
|
/// is "000" then milliseconds are not sent and the format changes to:
|
||||||
|
/// "%Y-%M-%DT%h:%m:%s". Is present only for the status "COMPLETED".
|
||||||
|
pub local_receipt_date_time: Option<String>,
|
||||||
|
/// Array of objects related to transaction identification. In case of
|
||||||
|
/// statuses:
|
||||||
|
/// * `"WAITING_FOR_CONFIRMATION"` and `"COMPLETED"` - Contains one element
|
||||||
|
/// with two parameters: name and value,
|
||||||
|
/// * `"PENDING"` - may contain object with aforementioned parameters or it
|
||||||
|
/// can be empty.
|
||||||
|
///
|
||||||
|
/// Also properties `name`
|
||||||
|
///
|
||||||
|
/// Static value. The payment identifier, displayed on transaction
|
||||||
|
/// statements as "Trans ID" and within the transaction search option in
|
||||||
|
/// the Management Panel.
|
||||||
|
///
|
||||||
|
/// Also properties `value`
|
||||||
|
///
|
||||||
|
/// Transaction ID in PayU system (data type - string).
|
||||||
|
pub properties: Option<Vec<Prop>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatusUpdate {
|
||||||
|
pub fn status(&self) -> PaymentStatus {
|
||||||
|
self.order.status
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See [crate::req::OrderCreate::ext_order_id]
|
||||||
|
pub fn ext_order_id(&self) -> &str {
|
||||||
|
self.order.ext_order_id.as_deref().unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_ext_order_id(&self) -> bool {
|
||||||
|
self.order.ext_order_id.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Refund notification object
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct RefundUpdate {
|
||||||
|
pub ext_order_id: String,
|
||||||
|
pub order_id: OrderId,
|
||||||
|
pub refund: Refund,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Refund {
|
||||||
|
pub refund_id: String,
|
||||||
|
pub amount: String,
|
||||||
|
pub currency_code: String,
|
||||||
|
pub status: RefundStatus,
|
||||||
|
pub status_date_time: String,
|
||||||
|
pub reason: String,
|
||||||
|
pub reason_description: String,
|
||||||
|
pub refund_date: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Order {
|
||||||
|
pub notify_url: Option<String>,
|
||||||
|
/// Customer client IP address
|
||||||
|
pub customer_ip: String,
|
||||||
|
/// Secret pos ip. This is connected to PayU account
|
||||||
|
#[serde(deserialize_with = "deserialize::deserialize_i32_newtype")]
|
||||||
|
pub merchant_pos_id: MerchantPosId,
|
||||||
|
/// Transaction description
|
||||||
|
pub description: String,
|
||||||
|
/// 3 characters currency identifier, ex. PLN
|
||||||
|
pub currency_code: String,
|
||||||
|
/// Total price of the order in pennies (e.g. 1000 is 10.00 EUR).
|
||||||
|
/// Applies also to currencies without subunits (e.g. 1000 is 10
|
||||||
|
/// HUF).
|
||||||
|
#[serde(deserialize_with = "deserialize::deserialize_i32")]
|
||||||
|
pub total_amount: Price,
|
||||||
|
/// @see [crate::Buyer]
|
||||||
|
pub buyer: Option<Buyer>,
|
||||||
|
/// List of products
|
||||||
|
pub products: Vec<Product>,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
pub order_create_date: Option<String>,
|
||||||
|
pub pay_method: Option<PayMethod>,
|
||||||
|
pub status: PaymentStatus,
|
||||||
|
pub ext_order_id: Option<String>,
|
||||||
|
}
|
@ -5,6 +5,33 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::credit::Credit;
|
use crate::credit::Credit;
|
||||||
pub use crate::model::*;
|
pub use crate::model::*;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum PaymentType {
|
||||||
|
Pbl,
|
||||||
|
CardToken,
|
||||||
|
Installments,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around pay method. It's used only for deserializing notifications
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pay_u::PayMethod;
|
||||||
|
/// let method: PayMethod = serde_json::from_str(r#"
|
||||||
|
/// {
|
||||||
|
/// "type": "INSTALLMENTS"
|
||||||
|
/// }
|
||||||
|
/// "#).unwrap();
|
||||||
|
/// ```
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PayMethod {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub payment_type: PaymentType,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Refund {
|
pub struct Refund {
|
||||||
|
Loading…
Reference in New Issue
Block a user