omnipay - AuthorizeNet_CIM - omnipay

I am trying to setup a payment processor using omnipay-authorizenet AuthorizeNet_CIM. Not a lot of documentation on this.
Step 1) I create the gateway object successfully and can make requests to the authorize.net sandbox server.
Step 2) is to "create a card" for future use with Token Billing: $gateway->createCard() . This is successful.
From the General Omnipay Token Billing documentation:
"... createCard($options) - returns a response object which includes a cardReference, which can be used for future transactions..."
I don't see a specific 'cardReference' in the above createCard() response object.
So I create a $cardRef array and grab the returned response CustomerProfileId and CustomerPaymentProfileId .
$profileResult['customerProfileId']=$response->getCustomerProfileId();
$profileResult['paymentProfileId']=$response->getCustomerPaymentProfileId();
Step 3) is a function to generate the purchase which fails:
function create_transaction($cardRef,$amount,$description,$invoice_number){
global $status, $gateway;
try {
// Send purchase request
$response = $gateway->purchase(
array(
'cardReference' => $cardRef ,
'amount' => $amount,
'currency' => 'USD',
'description' => $_POST['description'],
'transactionId' => $invoice_number
)
)->send();
if ($response->isSuccessful()) {
// Payment was successful
$status.='Success: '.$response->getMessage();
} elseif ($response->isRedirect()) {
// Redirect to offsite payment gateway
$response->redirect();
} else {
// Payment failed
$status.='Transaction Failure: '.$response->getMessage();
}
} catch (Exception $e) {
$status.='<strong>Error:</strong> '.$e->getMessage(). "<br/>";
}
}
The purchase fails and when I look at the Response object it seems the Request is not populating the cardReference object.
[cardReference] => Omnipay\AuthorizeNet\Model\CardReference Object
(
[customerProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
[paymentProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
[shippingProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
)
I am obviously not passing the correct cardReference data to the purchase method.
Any help would be greatly appreciated.
Thanks

I apparently needed to use the undocumented Omnipay method;
$response->getCardReference();
to get a cardReference object to pass to my create_transaction() function.
All fixed.
Thanks

Related

Testing updating user profile data

I make http tests in my Laravel 5.7 application with profile page(which has "Profile View" page and "Profile Details" editor ), like :
$newUser->save();
$testing_user_id = $newUser->id;
$newUserGroup = new UserGroup();
$newUserGroup->group_id = USER_ACCESS_USER;
$newUserGroup->user_id = $newUser->id;
$userGroup= Group::find($newUserGroup->group_id);
$newUserSessionData = [
[
'loggedUserAccessGroups' => ['group_id' => $newUserGroup->group_id, 'group_name' => !empty($userGroup) ? $userGroup->name : ''],
'logged_user_ip' => '0',
]
];
$newUserGroup->save();
// 3. OPEN PROFILE PAGE BLOCK START
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->get('/profile/view');
// 3. OPEN PROFILE PAGE BLOCK END
// 4. MAKING CHECKING PROFILE FOR USER CREATED AT 2) BLOCK START
$response->assertStatus(200); // to use HTTP_RESPONSE_OK
$response->assertSee(htmlspecialchars("Profile : " . $newUser->username, ENT_QUOTES));
// 4. MAKING CHECKING PROFILE FOR USER CREATED AT 2) BLOCK END
// 5. OPEN PROFILE DETAILS VIEW PAGE BLOCK START
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->get('profile/view');
$response->assertStatus(200);
$response->assertSee(htmlspecialchars("Profile : " . $newUser->username, ENT_QUOTES));
// 5. OPEN PROFILE DETAILS VIEW PAGE BLOCK END
// 6. OPEN PROFILE DETAILS EDITOR PAGE BLOCK START
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->get('profile/edit-details'); // http://local-votes.com/profile/edit-details
$response->assertStatus(HTTP_RESPONSE_OK);
$response->assertSee(htmlspecialchars("Profile : Details"));
// 6. OPEN PROFILE DETAILS EDITOR PAGE BLOCK END
// 7. MODIFY PROFILE DETAILS PAGE BLOCK START
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->post('profile/edit-details-post', [
'first_name' => 'Modified : ' . $newUser->first_name,
'last_name' => 'Modified : ' . $newUser->last_name,
'phone' => 'Modified : ' . $newUser->phone,
'website' => 'Modified : ' . $newUser->website,
'_token' => $csrf_token
]);
// $response->assertStatus(205); // ???
// 7. MODIFY PROFILE DETAILS PAGE BLOCK END
////////////////////////
// 8. OPEN PROFILE DETAILS VIEW PAGE AFTER MODIFICATIONS BLOCK START
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->get('profile/view');
$response->assertStatus(200);
$response->assertSee( htmlspecialchars('Modified : ' . $newUser->last_name) );
// 8. OPEN PROFILE DETAILS VIEW PAGE AFTER MODIFICATIONS BLOCK END
New user is added and Profile View page is opened ok, but there are problems at step // 7. MODIFY PROFILE DETAILS PAGE BLOCK START
as I see in sql trace new user is inserted but not updated.
In my control app/Http/Controllers/ProfileController.php update method is defined with validation request :
public function update_details(ProfileUserDetailsRequest $request)
{
$userProfile = Auth::user();
$requestData = $request->all();
$userProfile->first_name = $requestData['first_name'];
$userProfile->last_name = $requestData['last_name'];
$userProfile->phone = $requestData['phone'];
$userProfile->website = $requestData['website'];
$userProfile->updated_at = now();
$userProfile->save();
$this->setFlashMessage('Profile updated successfully !', 'success', 'Profile');
return Redirect::route('profile-view');
} // public function update_details(ProfileUserDetailsRequest $request)
1) Can the reason be in ProfileUserDetailsRequest and how to deal this ?
My profile details editor works ok.
My route defined as :
Route::group(array('prefix' => 'profile', 'middleware' => ['auth', 'isVerified']), function(){
Route::post('edit-details-post', array(
'as' => 'profile-edit-details-post',
'uses' => 'ProfileController#update_details'
));
At first I tried PUT, but after that I tried POST - the same without results.
2) Can you advice some proper way of User Profile details checking on // 7. MODIFY PROFILE DETAILS PAGE BLOCK START step ?
MODIFIED BLOCK # 2 :
I tried patch method, but it does not work anyway.
I have debugging method in my app/Http/Controllers/ProfileController.php
public function update_details(ProfileUserDetailsRequest $request)
{
method and when test is run I see that it is not triggered.
I use the same update_details method updating my form in brauser and it work ok(I see debugging info too).
I suppose that could be csrf issue and in header of my test file I wrote:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use DB;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\WithoutMiddleware; // Prevent all middleware from being executed for this test class.
public function testProfilePage()
{
$csrf_token = csrf_token();
...
$response = $this->actingAs($newUser)
->withSession($newUserSessionData)
->patch('profile/edit-details-post', [
'first_name' => 'Modified : ' . $newUser->first_name,
'last_name' => 'Modified : ' . $newUser->last_name,
'phone' => 'Modified : ' . $newUser->phone,
'website' => 'Modified : ' . $newUser->website,
// '_token' => $csrf_token / I TRIED TO UNCOMMENT THIS LINE TOO
]);
$response->assertStatus(205); // making this check I see that code 419 was returned
Can decision be to add in file app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
// ???
];
If in command line I run tests as
vendor/bin/phpunit tests/Feature/ProfilepageTest.php
What have I to add in except?
Thanks!
Other than the PATCH instead of POST following are my recommendations to test your code.
Instead of ProfileUserDetailsRequest try to use simple Request.
Try to log $request variable in your update function and check if the _token and _method are available, method should be PATCH and the request variables are posted correctly.
Make a model of user table and try to update the user with that model using
$user = User::find(Auth::user()->id);
…
$user->save();
Sessions are initiated with a middleware, i think if you are disabling the middleware, session will not work.
If you are using an IDE like Visual Studio Code to run your code then try using a debugger like xdebug. Place a breakpoint in your update_details method and see if it is getting to save and save is executing. If it is then we know save is not updating correctly.
It looks like what you are doing is correct according to the documentation for update:
https://laravel.com/docs/5.7/eloquent#updates example from docs below:
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();
Off the top of my head my only guess as to why it would fail is maybe getting the user off of the auth object causes problems. Take the id from the user in the auth object and use find() to grab the user then update its values and save and see if that works.

laravel 5.1 auth login returns an error

I'm trying to use auth()->login() in laravel 5.1 but it returns an error. Please see my code below:
$user = User::where('username', $username)->where('activation_code', $activation_code);
$not_activated_user = $user->where('status', 0)->where('confirmed', 0);
if($not_activated_user->count() == 1){
$not_activated_user->update([
'status' => 1,
'confirmed' => 1
]);
auth()->login($user->where('status', 1)->where('confirmed', 1));
}
I've also import use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; and implements AuthenticatableContract in my User model, but it still returns the same error. Why is that? I also tried to use ->get() in ->login(....->get()) to get the current user, but still same error.
Error:
Argument 1 passed to Illuminate\Auth\Guard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\Database\Eloquent\Builder given
Try
$user = User::where('username', $username)->where('activation_code', $activation_code)->firstOrFail();
$user->update([
'status' => 1,
'confirmed' => 1
]);
auth()->login($user);
}
It's working now, I just called the User model again to select the current user :)

Shopify API Updating Fulfillments

I am writing a private app in Shopify with PHP. I have been able to get most of the other access to the json data, however, I am having trouble with Fulfillments - specifically updating a single line-item.
I am using the api-skeleton (phpish)?
Here is my code (the process as described seems so simple):
$orderid = "1350520065";
$itemid = "2338134657";
$quantity = 1;
$arguments = array(
'fulfillment' => array(
'tracking_number' => null,
'notify_customer' => true,
'line_items' => array(array('id' => $itemid, 'quantity' => 1))
)
);
$response = $shopify('POST /admin/orders/' . $orderid . '/fulfillments.json', $arguments);
I am getting [line_items] => Required parameter missing or invalid.
Any help would be appreciated.
Skip the line items unless you are doing a partial fulfillment. If you are, then obviously you need a quantity. You forgot that it seems, hence your error of missing parameter.
Add a header 'Content-Type:application/json' to your POST. That worked for me.

PayPal SetExpressCheckOut API issue

I'm trying to implement the PayPal API function for SetExpressCheckout. Below I put a part of my code that I am using to call the payment process on the PayPal side. Everything looks fine. At the last step of the checkout, i push the "Pay Now" button and the payment is processed. After that user is returnet to my original site and i got the Transaction ID, success message and token. It looks like evrything was finished fine, but in my PayPal account i dont see any transactions and I don’t get any money at all.
$returnUrl = home_url("/wp-login.php?checkemail=registered&ppayment=done&price=".$package_price."&code=".$paypal_price_unit."&package=".$package_name."&pid=".$incomingpost);
$requestParams = array(
'RETURNURL' => $returnUrl,
'CANCELURL' => home_url('/wp-login.php?checkemail=registered&ppayment=cancel')
);
// Sent item info
$orderParams = array(
'PAYMENTREQUEST_0_AMT' => $package_price,
'PAYMENTREQUEST_0_SHIPPINGAMT' => '0',
'PAYMENTREQUEST_0_CURRENCYCODE' => $paypal_price_unit,
'PAYMENTREQUEST_0_ITEMAMT' => $package_price
);
//send package info
$item = array(
'L_PAYMENTREQUEST_0_NAME0' => $paymentName,
'L_PAYMENTREQUEST_0_DESC0' => $package_name,
'L_PAYMENTREQUEST_0_AMT0' => $package_price,
'L_PAYMENTREQUEST_0_QTY0' => '1'
);
//Call payment process
$infos = array();
$infos['USER'] = $paypal_api_user;
$infos['PWD'] = $paypal_api_pwd;
$infos['SIGNATURE'] = $paypal_api_signature;
if($paypal_sandbox == 1){$sandstatus = true;}else{$sandstatus = false;}
$paypal = new Paypal($infos,$sandstatus);
$response = $paypal -> request('SetExpressCheckout',$requestParams + $orderParams + $item);
if(is_array($response) && $response['ACK'] == 'Success') {
// We will redirecting now.
$token = $response['TOKEN'];
//Save DB before redirect.
$trans_post = array(
'post_status' => 'pending',
'post_type' => 'retransactions',
'post_title' => $token,
);
$new_post_id = wp_insert_post( $trans_post );
add_post_meta($new_post_id, 'webburemap_payment_user', $user_id);
add_post_meta($new_post_id, 'webburemap_payment_amount', $package_price);
add_post_meta($new_post_id, 'webburemap_payment_package_id', $package_IDNO);
add_post_meta($new_post_id, 'webburemap_payment_package_transtype', 'NewPackage');
if($paypal_sandbox == 0){
$commit = '&useraction=commit';
header( 'Location: https://www.paypal.com/webscr?cmd=_express-checkout&token=' . urlencode($token) . $commit ); //PayPal Pay Now
}else{
header( 'Location: https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=' . urlencode($token) );
}
die();
}
Can you provide the Express Checkout Token and the Transaction ID that you are getting back and I will take a look at it on my side to see what may be happening. Also make sure that you are pointing to the correct endpoint. If you are trying to process a live payment, make sure you are pointing towards the live site and not the sandbox.

Accessing magento's checkout/cart using REST API

I'm trying to integrate a cart-synchronisation-solution for my rest-clients.
The goal should be that I can have the same cart wherever I access my store from.
So I'll have to first of all deliver the existing items out to the client using the authenticated api-user.
But I get stuck at the very beginning:
protected function _retrieveCollection()
{
$cart = Mage::getSingleton('checkout/cart')->getQuote();
$cart->setCustomerId($this->getApiUser()->getUserId());
$cart->setStoreId(4);
$cart->load();
return $cart->getAllItems();
}
returns an empty array even though I have products in my cart.
Anyone any hints? Have that feeling I'm totally on the wrong side...
Found a solution. Getting the quote by Customer which is the other way around worked pretty well:
Mage::app()->setCurrentStore(4);
$cart = Mage::getModel('sales/quote')->loadByCustomer($this->getApiUser()->getUserId());
$items = array();
foreach ($cart->getAllVisibleItems() as $key => $item) {
$items[] = array(
'name' => $item->getName(),
'entity_id' => $item->getProductId(),
'description' => $item->getDescription(),
'final_price_with_tax' => $item->getBasePriceInclTax(),
'qty' => $item->getQty()
);
}