Authorize.Net transactionType - authorize.net-cim

As authorize.net (CIM) provides the facility of charging a credit card. Along with that the method createTransactionRequest requires transactionType parameter. I know that different transaction types are
AuthOnly
AuthCapture
CaptureOnly
PriorAuthCapture
Refund
Void
I want to know what is the meaning of these types and how I can make use of all these types available through API.

The abbreviations you list are defined CIM class properties:
private $_transactionTypes = array(
'AuthOnly',
'AuthCapture',
'CaptureOnly',
'PriorAuthCapture',
'Refund',
'Void',
);
See http://www.authorize.net/support/merchant/wwhelp/wwhimpl/js/html/wwhelp.htm for definitions of each type. You pass the type as the first parameter in createCustomerProfileTransaction:
$transaction = new AuthorizeNetTransaction;
// add more elements to $transaction
$response = $request->createCustomerProfileTransaction("AuthCapture", $transaction);

Related

How to create an entity when another is updating

I have two entities, the first is called Registration and is intended to store the user data while a confirmation email is used to activate the account. The second one is called Account and is the actual entity storing the user data that was previously in Registration.
I want this second entity to be created/persisted in the DB only after the user confirms its registration, at that stage the Registration entity will turn its flag isActive to true and will transfer the required data to the be persisted Account.
How to do that using the API platform?
Well, I found a way, although I don't know if it is the best approach: using a custom state processor.
Say we have two entities: Registration and Account. Registration will store the attempt to create an account while Account will store relevant data about the account once it is created. The are not related in any 'declared' way but the second depends on the first.
The logic is here: "How to use a custom state processor to create an entity when another is updating"
#[ApiResource]
#[Patch(
//...
processor: ActivateAccount::class
)]
class Registration
{
//...
}
and here is the ActivateAccount class:
class ActivateAccount implements ProcessorInterface
{
private ProcessorInterface $decorated;
private EntityManagerInterface $manager;
public function __construct(
ProcessorInterface $decorated,
EntityManagerInterface $manager
) {
$this->decorated = $decorated;
$this->manager = $manager;
}
public function process(
mixed $data,
Operation $operation,
array $uriVariables = [],
array $context = []
) {
if (!$data->isIsActive()) // we only want to create a new account if current registration is inactive
{
$account = new Account();
$account->setEmail($data->getEmail()); // get the email from the registration data
$account->setPassword($data->getPassword()); // get password from registration data, already hashed
$this->manager->persist($account); // save the account to DB
$this->manager->flush();
$data->setIsActive(true); // update the registration to prevent the attempt to create another caacount with this data
}
$this->decorated->process(
$data,
$operation,
$uriVariables,
$context
); // finally process the registration, this really means save the updated entity
}
}
This custom processor needs to be wired in services configuration:
services:
App\State\ActivateAccount:
bind:
$decorated: '#api_platform.doctrine.orm.state.persist_processor'
And the job is done!

With repository pattern, should I check first if the object queried exists in memory before it makes an actual database call

I have a repository, for example, UserRepository. It returns a user by given userId. I work on web application, so objects are loaded into memory, used, and disposed when the request ends.
So far, when I write a repository, I simply retrieved the data from the database. I don't store the retrieved User object into memory (I mean in a collection of the repository). When the repository's GetById() method is called, I don't check if the object is already in the collection. I simply query the database.
My questions are
Should I store retrieved objects in the memory, and when a repository's Get method is called, should I check if the object exists in the memory first before I make any Database call?
Or is the memory collection unnecessary, as web request is a short-lived session and all objects are disposed afterward
1) Should I store retrieved objects in the memory, and when a repository's Get method is called, should I check if the object exists in the memory first before I make any Database call?
Since your repository should be abstracted enough to simulate the purpose of an in-memory collection, I think it is really up to you and to your use case.
If you store your object after being retrieved from the database you will probably end-up with an implementation of the so-called IdentityMap. If you do this, it can get very complicated (well it depends on your domain).
Depending on the infrastructure layer you rely on, you may use the IdentityMap provided by your ORM if any.
But the real question is, is it worth implementing an IdentityMap?
I mean, we agree that repeating a query may be wrong for two reasons, performance and integrity, here a quote of Martin Fowler:
An old proverb says that a man with two watches never knows what time it is. If two watches are confusing, you can get in an even bigger mess with loading objects from a database.
But sometimes you need to be pragmatic and just load them every time you need it.
2) Or is the memory collection unnecessary, as web request is a short-lived session and all objects are disposed afterward
It depends™, for example, in some case you may have to play with your object in different place, in that case, it may be worth, but let's say you need to refresh your user session identity by loading your user from database, then there are cases where you only do it once within the whole request.
As is the usual case I don't think there is going to be a "one-size-fits-all".
There may be situations where one may implement a form of caching on a repository when the data is retrieved often, does not go stale too quickly, or simply for efficiency.
However, you could very well implement a type of generic cache decorator that can wrap a repository when you do need this.
So one should take each use case on merit.
When you're using an ORM like Entity Framework or NHibernate it's already taken care of - all read entities are tracked via IdentityMap mechanism, searching by keys (DbSet.Find in EF) won't even hit the database if the entity is already loaded.
If you're using direct database access or a microORM as base for your repository, you should be careful - without IdentityMap you're essentially working with value objects:
using System;
using System.Collections.Generic;
using System.Linq;
namespace test
{
internal class Program
{
static void Main()
{
Console.WriteLine("Identity map");
var artrepo1 = new ArticleIMRepository();
var o1 = new Order();
o1.OrderLines.Add(new OrderLine {Article = artrepo1.GetById(1, "a1", 100), Quantity = 50});
o1.OrderLines.Add(new OrderLine {Article = artrepo1.GetById(1, "a1", 100), Quantity = 30});
o1.OrderLines.Add(new OrderLine {Article = artrepo1.GetById(2, "a2", 100), Quantity = 20});
o1.ConfirmOrder();
o1.PrintChangedStock();
/*
Art. 1/a1, Stock: 20
Art. 2/a2, Stock: 80
*/
Console.WriteLine("Value objects");
var artrepo2 = new ArticleVORepository();
var o2 = new Order();
o2.OrderLines.Add(new OrderLine {Article = artrepo2.GetById(1, "a1", 100), Quantity = 50});
o2.OrderLines.Add(new OrderLine {Article = artrepo2.GetById(1, "a1", 100), Quantity = 30});
o2.OrderLines.Add(new OrderLine {Article = artrepo2.GetById(2, "a2", 100), Quantity = 20});
o2.ConfirmOrder();
o2.PrintChangedStock();
/*
Art. 1/a1, Stock: 50
Art. 1/a1, Stock: 70
Art. 2/a2, Stock: 80
*/
Console.ReadLine();
}
#region "Domain Model"
public class Order
{
public List<OrderLine> OrderLines = new List<OrderLine>();
public void ConfirmOrder()
{
foreach (OrderLine line in OrderLines)
{
line.Article.Stock -= line.Quantity;
}
}
public void PrintChangedStock()
{
foreach (var a in OrderLines.Select(x => x.Article).Distinct())
{
Console.WriteLine("Art. {0}/{1}, Stock: {2}", a.Id, a.Name, a.Stock);
}
}
}
public class OrderLine
{
public Article Article;
public int Quantity;
}
public class Article
{
public int Id;
public string Name;
public int Stock;
}
#endregion
#region Repositories
public class ArticleIMRepository
{
private static readonly Dictionary<int, Article> Articles = new Dictionary<int, Article>();
public Article GetById(int id, string name, int stock)
{
if (!Articles.ContainsKey(id))
Articles.Add(id, new Article {Id = id, Name = name, Stock = stock});
return Articles[id];
}
}
public class ArticleVORepository
{
public Article GetById(int id, string name, int stock)
{
return new Article {Id = id, Name = name, Stock = stock};
}
}
#endregion
}
}

CGridview With Custom Dataprovider That Doesn't Load All Records From Source (Lazy Loading)

I'm a 5-day Yii fan trying to learn the ropes of this great framework. I would really appreciate it if you could bear with me reading through my problem and help me out.
So here goes, I'm retrieving a list of products sold by a particular merchant of an online marketplace through its web service. When I query the web service like this
api.marketplace.com?merchant_id=1234
I'll get back the response in JSON which consists of two main pieces of data
The number of products sold by Merchant 1234 (total_products)
The list (array) of the products sold (list_product). Each element in this array represents one distinct Product object with two fields: product_id and product_name respectively.
So if total_products = 934, there'll be 934 elements in the array.
When I put it in codes, my derived DataProvider looks like this
class ProductDataProvider extends CDataProvider /* or should I extend other better class? */ {
public function __construct($config = array()) {
foreach($config as $key=>$value)
$this->$key=$value;
}
protected function fetchData() {
$request = "api.marketplace.com?merchant_id=1234";
$response = retrieveProductsAndProcessJSONResponseIntoAppropriateDataStructure($request);
$this->setTotalItemCount($response->total_products);
if(($pagination=$this->getPagination())!==false)
$pagination->setItemCount($this->getTotalItemCount());
return $response->list_products;
}
protected function calculateTotalItemCount() {
return $this->getTotalItemCount();
}
}
My model
class Product extends CModel {
public $product_id;
public $product_name;
public function display() {
return new ProductDataProvider(array(
'pagination'=>array(
'pageSize'=>10,
));
}
}
and my View
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'product-grid',
'dataProvider'=>$model->display(),
'columns'=>array(
'product_id',
'product_name',
),
));
This works well with pagination and all that. However retrieving all 934 products is taking a bit too long. We can do this to the web service.
api.marketplace.com?merchant_id=1234&page_size=10&page_no=1
This will only retrieve the first 10 records. We can play around with the query string variable page_no to retrieve subsequent pages of products in groups of 10. The total_products returned from the web service will still be 934.
So my question is, how do I put this into play so that the ProductDataProvider only retrieves 10 product at any one time and load it into CGridView? The CGridView will have to know that there are a total of 934 products to enable pagination. User browsing to other pages of the CGridView will trigger the ProductDataProvider to retrieve the next 10 records corresponding to the page number being viewed. I hope that my long winded question is comprehensible.
I had the same issue. So, I think:
Firstly, you should implement all 3 abstract methods from CDataProvider. In your class fetchKeys() is not implemented.
Secondly, pagination logic should be put in fetchData. For instance:
protected function fetchData() {
$request = "api.marketplace.com?merchant_id=1234";
// page size
$request .= "&page_size=".$this->pagination->pageSize;
// current page
$request .= "&page_no=".$this->pagination->currentPage;
$response = retrieveProductsAndProcessJSONResponseIntoAppropriateDataStructure($request);
return $response->list_products;
}
To use your new custom data provider write smth like that:
$dataProvider = new CustomDataProvider();
$pages = new CPagination($dataProvider->getTotalItemCount());
$pages->pageSize = 40; // page size
$dataProvider->pagination = $pages;
Data providers get total number of items using calculateTotalItemCount(). So, in addition, you should write there some logic to provide total item count. Guess, you should exploit another method in your API for that purpose. Remember, that if you use pagination, your data provider will do 2 api requests: the first for total item count and the second for current page items. Some can say that only one request is enough, but in this case, that request will return all data (934 elements). So heavy.
That's all you need.
I think that you need to create your own custom data provider. See the Class Reference for CDataProvider
There are three implemented data providers in Yii. CActiveDataProvider, CArrayDataProvider, and CSqlDataProvider. You can use those as a model for your custom data provider.

paypal PPAPIService new SDK

Concerning the new Paypal SDK, there is almost no useful example code, and the Internet is littered with examples of the old SDK. My question concerns making an API request for a third party paypal account for which i have obtained the token and secretToken through the permissions API.
In attempting to construct a PPAPIService object, where is the list of possible sevice names?
ie: $this->serviceName = $serviceName; (in the constructor) What is the string syntax for these?
In regards to the makeRequest method, how do I define the $apiMethod variable, and what is the format of the $params variable? What are the different parameters?
A simple example of how to just obtain the account balance of the authorized third party account would be extremely helpful.
I am using PHP.
from the PPAPIService.php file:
class PPAPIService
{
public $endpoint;
public $serviceName;
private $logger;
public function __construct($serviceName = "")
{
$this->serviceName = $serviceName; //is there ANY documentation about the syntax and types of service names?
$config = PPConfigManager::getInstance();
$this->endpoint = $config->get('service.EndPoint');
$this->logger = new PPLoggingManager(__CLASS__);
}
public function setServiceName($serviceName)
{
$this->serviceName = $serviceName;
}
public function makeRequest($apiMethod, $params, $apiUsername = null, $accessToken = null, $tokenSecret = null)
{
//what are the apiMethod types? syntax? and params? type.. options...??
}
}
Well, you do not have to create a PPAPIService object directly. Let's say you want to use the Invoicing SDK, here's what you would do
$invoiceService = new InvoiceService();
$invoiceService->setAccessToken($accessToken);
$invoiceService->setTokenSecret($tokenSecret);
$createInvoiceResponse = $invoiceService->CreateInvoice($createInvoiceRequest);
There's one service class (such as InvoiceService in this code snippet) per API that you would instantiate as per your needs. The API username/password are picked from the configuration file and the access token/token secret are set via code since they typically tend to be different for different invocations.
Which API are you trying to call, by the way?
To answer on your other concern, the new PayPal SDK's have all the required samples bundled within the SDK itself. The SDK + Samples canbe downloaded from
https://www.x.com/developers/paypal/documentation-tools/paypal-sdk-index

Yii Framework: CModel replicating CActiveRecord functionality with WebServices

Has anyone tried or found an example of a class derived from CModel that replicates CActiveRecord functionality with WebServices instead of database connection???
If done with RESTFULL WebServices it would be great. If data is transmitted JSON encoded, wonderful!!...
I'd appretiate your help. Thanks.
I spend a lot of time looking for that as well, I came across this Yii extension on Github:
https://github.com/Haensel/ActiveResource
It allows you to have exactly what you are looking for, the readme isn't updated with the changes reflected in changes.md, so I recommend you read through this document as well.
EActiveResource for Yii
...is an extension for the Yii PHP framework allowing the user to create models that use RESTful services as persistent storage.
The implementation is inspired by Yii's CActiveRecord class and the Ruby on Rails implementation of ActiveResource (http://api.rubyonrails.org/classes/ActiveResource/Base.html).
HINT:
CAUTION: THIS IS STILL AN ALPHA RELEASE!
This project started as a draft and is still under development, so as long is there is no 1.0 release you may experience changes that could break your code. Look at the CHANGES.md file for further information
As there are thousands of different REST services out there that use a thousand different approaches it can be tricky to debug errors. Because of that I added extensive
tracing to all major functions, so you should always be able to see every request, which method it used and how the service responded. Just enable the tracing functionality of Yii
and look for the category "ext.EActiveResource"
INSTALL:
Add the extension to Yii by placing it in your application's extension folder (for example '/protected/extensions')
Edit your applications main.php config file and add 'application.extensions.EActiveResource.*' to your import definitions
Add the configuration for your resources to the main config
'activeresource'=>array(
'class'=>'EActiveResourceConnection',
'site'=>'http://api.aRESTservice.com',
'contentType'=>'application/json',
'acceptType'=>'application/json',
)),
'queryCacheId'=>'SomeCacheComponent')
4.) Now create a class extending EActiveResource like this (don't forget the model() function!):
QUICK OVERVIEW:
class Person extends EActiveResource
{
/* The id that uniquely identifies a person. This attribute is not defined as a property
* because we don't want to send it back to the service like a name, surname or gender etc.
*/
public $id;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function rest()
{
return CMap::mergeArray(
parent::rest(),
array(
'resource'=>'people',
)
);
}
/* Let's define some properties and their datatypes
public function properties()
{
return array(
'name'=>array('type'=>'string'),
'surname'=>array('type'=>'string'),
'gender'=>array('type'=>'string'),
'age'=>array('type'=>'integer'),
'married'=>array('type'=>'boolean'),
'salary'=>array('type'=>'double'),
);
}
/* Define rules as usual */
public function rules()
{
return array(
array('name,surname,gender,age,married,salary','safe'),
array('age','numerical','integerOnly'=>true),
array('married','boolean'),
array('salary','numerical')
);
}
/* Add some custom labels for forms etc. */
public function attributeLabels()
{
return array(
'name'=>'First name',
'surname'=>'Last name',
'salary'=>'Your monthly salary',
);
}
}
Usage:
/* sends GET to http://api.example.com/person/1 and populates a single Person model*/
$person=Person::model()->findById(1);
/* sends GET to http://api.example.com/person and populates Person models with the response */
$persons=Person::model()->findAll();
/* create a resource
$person=new Person;
$person->name='A name';
$person->age=21;
$person->save(); //New resource, send POST request. Returns false if the model doesn't validate
/* Updating a resource (sending a PUT request)
$person=Person::model()->findById(1);
$person->name='Another name';
$person->save(); //Not at new resource, update it. Returns false if the model doesn't validate
//or short version
Person::model()->updateById(1,array('name'=>'Another name'));
/* DELETE a resource
$person=Person::model()->findById(1);
$person->destroy(); //DELETE to http://api.example.com/person/1
//or short version
Person::model()->deleteById(1);
Hope this helps you