I am working with a application using codeigniter 2.2 but now I am encountering a problem with integrating wepay library wepay.php into codeigniter library. Any help would be appreciated Here is the current library provided by wepay.
I have tried to integrate wepay.php into codeigniter but it gives white screen. I think there is an issue with multiple classes being defined in wepay.php and I dont know how to handle this in codeigniter
Openaccount.php file:
<?php
require './_shared.php';
?>
<h1>WePay Demo App: Open Account</h1>
Back
<br />
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['account_name']) && isset($_POST['account_description'])) {
// WePay sanitizes its own data, but displaying raw POST data on your own site is a XSS security hole.
$name = htmlentities($_POST['account_name']);
$desc = htmlentities($_POST['account_description']);
try {
$wepay = new WePay('STAGE_5cdbb3fa32af0ccaef97328542d5e2a0a7f61263ed2bcd79c9f29c2d5e0d85e6');
$account = $wepay->request('account/create', array(
'name' => $name,
'description' => $desc,
));
echo "Created account $name for '$desc'! View on WePay at $account->account_uri. See all of your accounts here.";
}
catch (WePayException $e) {
// Something went wrong - normally you would log
// this and give your user a more informative message
echo $e->getMessage();
}
}
else {
echo 'Account name and description are both required.';
}
}
?>
<form method="post">
<fieldset>
<legend>Account Info</legend>
<label for="account_name">Account Name:</label><br />
<input type="text" id="account_name" name="account_name" placeholder="Ski Trip Savings"/>
<br /><br />
<label for="account_description">Account Description: </label><br />
<textarea name="account_description" rows="10" cols="40" placeholder="Saving up some dough for our ski trip!"></textarea>
<br /><br />
<input type="submit" value="Open account" />
</fieldset>
</form>
shared.php file:
<?php
require '../wepay.php';
Wepay::useStaging('34218', '7c09762bbe','2014-01-08');
session_start();
?>
Please have a look at the bottom of wepay.php it is multiple classes defined in one class.
wepay.php contents
<?php
class WePay {
/**
* Version number - sent in user agent string
*/
const VERSION = '0.2.1';
/**
* Scope fields
* Passed into Wepay::getAuthorizationUri as array
*/
const SCOPE_MANAGE_ACCOUNTS = 'manage_accounts'; // Open and interact with accounts
const SCOPE_COLLECT_PAYMENTS = 'collect_payments'; // Create and interact with checkouts
const SCOPE_VIEW_USER = 'view_user'; // Get details about authenticated user
const SCOPE_PREAPPROVE_PAYMENTS = 'preapprove_payments'; // Create and interact with preapprovals
const SCOPE_MANAGE_SUBSCRIPTIONS = 'manage_subscriptions'; // Subscriptions
const SCOPE_SEND_MONEY = 'send_money'; // For withdrawals
/**
* Application's client ID
*/
private static $client_id;
/**
* Application's client secret
*/
private static $client_secret;
/**
* API Version
* https://www.wepay.com/developer/reference/versioning
*/
private static $api_version;
/**
* #deprecated Use WePay::getAllScopes() instead.
*/
public static $all_scopes = array(
self::SCOPE_MANAGE_ACCOUNTS,
self::SCOPE_COLLECT_PAYMENTS,
self::SCOPE_PREAPPROVE_PAYMENTS,
self::SCOPE_VIEW_USER,
self::SCOPE_SEND_MONEY,
self::SCOPE_MANAGE_SUBSCRIPTIONS
);
/**
* Determines whether to use WePay's staging or production servers
*/
private static $production = null;
/**
* cURL handle
*/
private static $ch = NULL;
/**
* Authenticated user's access token
*/
private $token;
/**
* Pass WePay::getAllScopes() into getAuthorizationUri if your application desires full access
*/
public static function getAllScopes() {
return array(
self::SCOPE_MANAGE_ACCOUNTS,
self::SCOPE_MANAGE_SUBSCRIPTIONS,
self::SCOPE_COLLECT_PAYMENTS,
self::SCOPE_PREAPPROVE_PAYMENTS,
self::SCOPE_VIEW_USER,
self::SCOPE_SEND_MONEY
);
}
/**
* Generate URI used during oAuth authorization
* Redirect your user to this URI where they can grant your application
* permission to make API calls
* #link https://www.wepay.com/developer/reference/oauth2
* #param array $scope List of scope fields for which your application wants access
* #param string $redirect_uri Where user goes after logging in at WePay (domain must match application settings)
* #param array $options optional user_name,user_email which will be pre-filled on login form, state to be returned in querystring of redirect_uri
* #return string URI to which you must redirect your user to grant access to your application
*/
public static function getAuthorizationUri(array $scope, $redirect_uri, array $options = array()) {
// This does not use WePay::getDomain() because the user authentication
// domain is different than the API call domain
if (self::$production === null) {
throw new RuntimeException('You must initialize the WePay SDK with WePay::useStaging() or WePay::useProduction()');
}
$domain = self::$production ? 'https://www.wepay.com' : 'https://stage.wepay.com';
$uri = $domain . '/v2/oauth2/authorize?';
$uri .= http_build_query(array(
'client_id' => self::$client_id,
'redirect_uri' => $redirect_uri,
'scope' => implode(',', $scope),
'state' => empty($options['state']) ? '' : $options['state'],
'user_name' => empty($options['user_name']) ? '' : $options['user_name'],
'user_email' => empty($options['user_email']) ? '' : $options['user_email'],
), '', '&');
return $uri;
}
private static function getDomain() {
if (self::$production === true) {
return 'https://wepayapi.com/v2/';
}
elseif (self::$production === false) {
return 'https://stage.wepayapi.com/v2/';
}
else {
throw new RuntimeException('You must initialize the WePay SDK with WePay::useStaging() or WePay::useProduction()');
}
}
/**
* Exchange a temporary access code for a (semi-)permanent access token
* #param string $code 'code' field from query string passed to your redirect_uri page
* #param string $redirect_uri Where user went after logging in at WePay (must match value from getAuthorizationUri)
* #return StdClass|false
* user_id
* access_token
* token_type
*/
public static function getToken($code, $redirect_uri) {
$params = (array(
'client_id' => self::$client_id,
'client_secret' => self::$client_secret,
'redirect_uri' => $redirect_uri,
'code' => $code,
'state' => '', // do not hardcode
));
$result = self::make_request('oauth2/token', $params);
return $result;
}
/**
* Configure SDK to run against WePay's production servers
* #param string $client_id Your application's client id
* #param string $client_secret Your application's client secret
* #return void
* #throws RuntimeException
*/
public static function useProduction($client_id, $client_secret, $api_version = null) {
if (self::$production !== null) {
throw new RuntimeException('API mode has already been set.');
}
self::$production = true;
self::$client_id = $client_id;
self::$client_secret = $client_secret;
self::$api_version = $api_version;
}
/**
* Configure SDK to run against WePay's staging servers
* #param string $client_id Your application's client id
* #param string $client_secret Your application's client secret
* #return void
* #throws RuntimeException
*/
public static function useStaging($client_id, $client_secret, $api_version = null) {
if (self::$production !== null) {
throw new RuntimeException('API mode has already been set.');
}
self::$production = false;
self::$client_id = $client_id;
self::$client_secret = $client_secret;
self::$api_version = $api_version;
}
/**
* Returns the current environment.
* #return string "none" (not configured), "production" or "staging".
*/
public static function getEnvironment() {
if(self::$production === null) {
return 'none';
} else if(self::$production) {
return 'production';
} else {
return 'staging';
}
}
/**
* Set Api Version
* https://www.wepay.com/developer/reference/versioning
*
* #param string $version Api Version to send in call request header
*/
public static function setApiVersion($version) {
self::$api_version = $version;
}
/**
* Create a new API session
* #param string $token - access_token returned from WePay::getToken
*/
public function __construct($token) {
if ($token && !is_string($token)) {
throw new InvalidArgumentException('$token must be a string, ' . gettype($token) . ' provided');
}
$this->token = $token;
}
/**
* Clean up cURL handle
*/
public function __destruct() {
if (self::$ch) {
curl_close(self::$ch);
self::$ch = NULL;
}
}
/**
* create the cURL request and execute it
*/
private static function make_request($endpoint, $values, $headers = array())
{
self::$ch = curl_init();
$headers = array_merge(array("Content-Type: application/json"), $headers); // always pass the correct Content-Type header
// send Api Version header
if(!empty(self::$api_version)) {
$headers[] = "Api-Version: " . self::$api_version;
}
curl_setopt(self::$ch, CURLOPT_USERAGENT, 'WePay v2 PHP SDK v' . self::VERSION . ' Client id:' . self::$client_id);
curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt(self::$ch, CURLOPT_TIMEOUT, 30); // 30-second timeout, adjust to taste
curl_setopt(self::$ch, CURLOPT_POST, !empty($values)); // WePay's API is not strictly RESTful, so all requests are sent as POST unless there are no request values
$uri = self::getDomain() . $endpoint;
curl_setopt(self::$ch, CURLOPT_URL, $uri);
if (!empty($values)) {
curl_setopt(self::$ch, CURLOPT_POSTFIELDS, json_encode($values));
}
$raw = curl_exec(self::$ch);
if ($errno = curl_errno(self::$ch)) {
// Set up special handling for request timeouts
if ($errno == CURLE_OPERATION_TIMEOUTED) {
throw new WePayServerException("Timeout occurred while trying to connect to WePay");
}
throw new Exception('cURL error while making API call to WePay: ' . curl_error(self::$ch), $errno);
}
$result = json_decode($raw);
$httpCode = curl_getinfo(self::$ch, CURLINFO_HTTP_CODE);
if ($httpCode >= 400) {
if (!isset($result->error_code)) {
throw new WePayServerException("WePay returned an error response with no error_code, please alert api#wepay.com. Original message: $result->error_description", $httpCode, $result, 0);
}
if ($httpCode >= 500) {
throw new WePayServerException($result->error_description, $httpCode, $result, $result->error_code);
}
switch ($result->error) {
case 'invalid_request':
throw new WePayRequestException($result->error_description, $httpCode, $result, $result->error_code);
case 'access_denied':
default:
throw new WePayPermissionException($result->error_description, $httpCode, $result, $result->error_code);
}
}
return $result;
}
/**
* Make API calls against authenticated user
* #param string $endpoint - API call to make (ex. 'user', 'account/find')
* #param array $values - Associative array of values to send in API call
* #return StdClass
* #throws WePayException on failure
* #throws Exception on catastrophic failure (non-WePay-specific cURL errors)
*/
public function request($endpoint, array $values = array()) {
$headers = array();
if ($this->token) { // if we have an access_token, add it to the Authorization header
$headers[] = "Authorization: Bearer $this->token";
}
$result = self::make_request($endpoint, $values, $headers);
return $result;
}
}
/**
* Different problems will have different exception types so you can
* catch and handle them differently.
*
* WePayServerException indicates some sort of 500-level error code and
* was unavoidable from your perspective. You may need to re-run the
* call, or check whether it was received (use a "find" call with your
* reference_id and make a decision based on the response)
*
* WePayRequestException indicates a development error - invalid endpoint,
* erroneous parameter, etc.
*
* WePayPermissionException indicates your authorization token has expired,
* was revoked, or is lacking in scope for the call you made
*/
class WePayException extends Exception {
public function __construct($description = '', $http_code = FALSE, $response = FALSE, $code = 0, $previous = NULL)
{
$this->response = $response;
if (!defined('PHP_VERSION_ID')) {
$version = explode('.', PHP_VERSION);
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}
if (PHP_VERSION_ID < 50300) {
parent::__construct($description, $code);
} else {
parent::__construct($description, $code, $previous);
}
}
}
class WePayRequestException extends WePayException {}
class WePayPermissionException extends WePayException {}
class WePayServerException extends WePayException {}
Here is the solution to integrate wepay library in codeigniter
Go to application/config/config.php and add the following wepay app credentials at the end
config.php you can also make separate config file but I had included it in CI's config
/*WEPAY config items*/
$config['client_id']='client_id_here';
$config['client_secret']='client_secret_here';
$config['app_version']='2014-01-08'; // this could be different in future
$config['access_token']='access_token_here';
/* End of file config.php */
/* Location: ./application/config/config.php */
create a file name wepay.php in Codeigniter's application/libraries/wepay.php and paste the following contents in wepay.php at line 202 add your app's access token and also remember to remove line 234 of wepay.php as u go live, I added this line of code to stop curl from verifying SSL certificate.
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, 0);
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class WePay {
/**
* Version number - sent in user agent string
*/
const VERSION = '0.2.1';
/**
* Scope fields
* Passed into Wepay::getAuthorizationUri as array
*/
const SCOPE_MANAGE_ACCOUNTS = 'manage_accounts'; // Open and interact with accounts
const SCOPE_COLLECT_PAYMENTS = 'collect_payments'; // Create and interact with checkouts
const SCOPE_VIEW_USER = 'view_user'; // Get details about authenticated user
const SCOPE_PREAPPROVE_PAYMENTS = 'preapprove_payments'; // Create and interact with preapprovals
const SCOPE_MANAGE_SUBSCRIPTIONS = 'manage_subscriptions'; // Subscriptions
const SCOPE_SEND_MONEY = 'send_money'; // For withdrawals
/**
* Application's client ID
*/
private static $client_id;
/**
* Application's client secret
*/
private static $client_secret;
/**
* API Version
* https://www.wepay.com/developer/reference/versioning
*/
private static $api_version;
/**
* #deprecated Use WePay::getAllScopes() instead.
*/
public static $all_scopes = array(
self::SCOPE_MANAGE_ACCOUNTS,
self::SCOPE_COLLECT_PAYMENTS,
self::SCOPE_PREAPPROVE_PAYMENTS,
self::SCOPE_VIEW_USER,
self::SCOPE_SEND_MONEY,
self::SCOPE_MANAGE_SUBSCRIPTIONS
);
/**
* Determines whether to use WePay's staging or production servers
*/
private static $production = null;
/**
* cURL handle
*/
private static $ch = NULL;
/**
* Authenticated user's access token
*/
private $token;
/**
* Pass WePay::getAllScopes() into getAuthorizationUri if your application desires full access
*/
public static function getAllScopes() {
return array(
self::SCOPE_MANAGE_ACCOUNTS,
self::SCOPE_MANAGE_SUBSCRIPTIONS,
self::SCOPE_COLLECT_PAYMENTS,
self::SCOPE_PREAPPROVE_PAYMENTS,
self::SCOPE_VIEW_USER,
self::SCOPE_SEND_MONEY
);
}
/**
* Generate URI used during oAuth authorization
* Redirect your user to this URI where they can grant your application
* permission to make API calls
* #link https://www.wepay.com/developer/reference/oauth2
* #param array $scope List of scope fields for which your application wants access
* #param string $redirect_uri Where user goes after logging in at WePay (domain must match application settings)
* #param array $options optional user_name,user_email which will be pre-filled on login form, state to be returned in querystring of redirect_uri
* #return string URI to which you must redirect your user to grant access to your application
*/
public static function getAuthorizationUri(array $scope, $redirect_uri, array $options = array()) {
// This does not use WePay::getDomain() because the user authentication
// domain is different than the API call domain
if (self::$production === null) {
throw new RuntimeException('You must initialize the WePay SDK with WePay::useStaging() or WePay::useProduction()');
}
$domain = self::$production ? 'https://www.wepay.com' : 'https://stage.wepay.com';
$uri = $domain . '/v2/oauth2/authorize?';
$uri .= http_build_query(array(
'client_id' => self::$client_id,
'redirect_uri' => $redirect_uri,
'scope' => implode(',', $scope),
'state' => empty($options['state']) ? '' : $options['state'],
'user_name' => empty($options['user_name']) ? '' : $options['user_name'],
'user_email' => empty($options['user_email']) ? '' : $options['user_email'],
), '', '&');
return $uri;
}
private static function getDomain() {
if (self::$production === true) {
return 'https://wepayapi.com/v2/';
}
elseif (self::$production === false) {
return 'https://stage.wepayapi.com/v2/';
}
else {
throw new RuntimeException('You must initialize the WePay SDK with WePay::useStaging() or WePay::useProduction()');
}
}
/**
* Exchange a temporary access code for a (semi-)permanent access token
* #param string $code 'code' field from query string passed to your redirect_uri page
* #param string $redirect_uri Where user went after logging in at WePay (must match value from getAuthorizationUri)
* #return StdClass|false
* user_id
* access_token
* token_type
*/
public static function getToken($code, $redirect_uri) {
$params = (array(
'client_id' => self::$client_id,
'client_secret' => self::$client_secret,
'redirect_uri' => $redirect_uri,
'code' => $code,
'state' => '', // do not hardcode
));
$result = self::make_request('oauth2/token', $params);
return $result;
}
/**
* Configure SDK to run against WePay's production servers
* #param string $client_id Your application's client id
* #param string $client_secret Your application's client secret
* #return void
* #throws RuntimeException
*/
public static function useProduction($client_id, $client_secret, $api_version = null) {
if (self::$production !== null) {
throw new RuntimeException('API mode has already been set.');
}
self::$production = true;
self::$client_id = $client_id;
self::$client_secret = $client_secret;
self::$api_version = $api_version;
}
/**
* Configure SDK to run against WePay's staging servers
* #param string $client_id Your application's client id
* #param string $client_secret Your application's client secret
* #return void
* #throws RuntimeException
*/
public static function useStaging($client_id, $client_secret, $api_version = null) {
if (self::$production !== null) {
throw new RuntimeException('API mode has already been set.');
}
self::$production = false;
self::$client_id = $client_id;
self::$client_secret = $client_secret;
self::$api_version = $api_version;
}
/**
* Returns the current environment.
* #return string "none" (not configured), "production" or "staging".
*/
public static function getEnvironment() {
if(self::$production === null) {
return 'none';
} else if(self::$production) {
return 'production';
} else {
return 'staging';
}
}
/**
* Set Api Version
* https://www.wepay.com/developer/reference/versioning
*
* #param string $version Api Version to send in call request header
*/
public static function setApiVersion($version) {
self::$api_version = $version;
}
/**
* Create a new API session
* #param string $token - access_token returned from WePay::getToken
*/
public function __construct() {
$token='your_application_access_token';
if ($token && !is_string($token)) {
throw new InvalidArgumentException('$token must be a string, ' . gettype($token) . ' provided');
}
$this->token = $token;
}
/**
* Clean up cURL handle
*/
public function __destruct() {
if (self::$ch) {
curl_close(self::$ch);
self::$ch = NULL;
}
}
/**
* create the cURL request and execute it
*/
private static function make_request($endpoint, $values, $headers = array())
{
self::$ch = curl_init();
$headers = array_merge(array("Content-Type: application/json"), $headers); // always pass the correct Content-Type header
// send Api Version header
if(!empty(self::$api_version)) {
$headers[] = "Api-Version: " . self::$api_version;
}
curl_setopt(self::$ch, CURLOPT_USERAGENT, 'WePay v2 PHP SDK v' . self::VERSION . ' Client id:' . self::$client_id);
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, 0); // Remove this line after testing because this line is to stop curl from using ssl verification
curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt(self::$ch, CURLOPT_TIMEOUT, 30); // 30-second timeout, adjust to taste
curl_setopt(self::$ch, CURLOPT_POST, !empty($values)); // WePay's API is not strictly RESTful, so all requests are sent as POST unless there are no request values
$uri = self::getDomain() . $endpoint;
curl_setopt(self::$ch, CURLOPT_URL, $uri);
if (!empty($values)) {
curl_setopt(self::$ch, CURLOPT_POSTFIELDS, json_encode($values));
}
$raw = curl_exec(self::$ch);
if ($errno = curl_errno(self::$ch)) {
// Set up special handling for request timeouts
if ($errno == CURLE_OPERATION_TIMEOUTED) {
throw new WePayServerException("Timeout occurred while trying to connect to WePay");
}
throw new Exception('cURL error while making API call to WePay: ' . curl_error(self::$ch), $errno);
}
$result = json_decode($raw);
$httpCode = curl_getinfo(self::$ch, CURLINFO_HTTP_CODE);
if ($httpCode >= 400) {
if (!isset($result->error_code)) {
throw new WePayServerException("WePay returned an error response with no error_code, please alert api#wepay.com. Original message: $result->error_description", $httpCode, $result, 0);
}
if ($httpCode >= 500) {
throw new WePayServerException($result->error_description, $httpCode, $result, $result->error_code);
}
switch ($result->error) {
case 'invalid_request':
throw new WePayRequestException($result->error_description, $httpCode, $result, $result->error_code);
case 'access_denied':
default:
throw new WePayPermissionException($result->error_description, $httpCode, $result, $result->error_code);
}
}
return $result;
}
/**
* Make API calls against authenticated user
* #param string $endpoint - API call to make (ex. 'user', 'account/find')
* #param array $values - Associative array of values to send in API call
* #return StdClass
* #throws WePayException on failure
* #throws Exception on catastrophic failure (non-WePay-specific cURL errors)
*/
public function request($endpoint, array $values = array()) {
$headers = array();
if ($this->token) { // if we have an access_token, add it to the Authorization header
$headers[] = "Authorization: Bearer $this->token";
}
$result = self::make_request($endpoint, $values, $headers);
return $result;
}
}
/**
* Different problems will have different exception types so you can
* catch and handle them differently.
*
* WePayServerException indicates some sort of 500-level error code and
* was unavoidable from your perspective. You may need to re-run the
* call, or check whether it was received (use a "find" call with your
* reference_id and make a decision based on the response)
*
* WePayRequestException indicates a development error - invalid endpoint,
* erroneous parameter, etc.
*
* WePayPermissionException indicates your authorization token has expired,
* was revoked, or is lacking in scope for the call you made
*/
class WePayException extends Exception {
public function __construct($description = '', $http_code = FALSE, $response = FALSE, $code = 0, $previous = NULL)
{
$this->response = $response;
if (!defined('PHP_VERSION_ID')) {
$version = explode('.', PHP_VERSION);
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}
if (PHP_VERSION_ID < 50300) {
parent::__construct($description, $code);
} else {
parent::__construct($description, $code, $previous);
}
}
}
class WePayRequestException extends WePayException {}
class WePayPermissionException extends WePayException {}
class WePayServerException extends WePayException {}
Now the final step make a controller, here my controller name is payment here are its contents:
application/controllers/payment.php
After that you can call controller method by adding controller name and method in browser localhost/yourapplication/index.php/payment/test_wepay_response
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Payment extends CI_Controller {
public function __construct()
{
parent::__construct();
if($this->session->userdata('urole') != 'admin'){redirect('admin_login');}
$this->load->library('wePay','wepay');
$this->load->model('admin_model','admin');
}
public function index()
{ echo 'Hi there library loaded';exit;
}
public function test_wepay_response()
{
$client_id=$this->config->item('client_id');
$client_secret= $this->config->item('client_secret');
$client_secret= $this->config->item('app_version');
$this->wepay->useStaging($client_id,$client_secret,$app_version);
//$data = array('account_id' => '12345');
$response =$this->wepay->request('account/find');
print_r($response);exit;
}
}
Related
In my API, my controllers extend from BaseController and my endpoints send responses using the sendResponse method (this is my BaseController):
class BaseController extends Controller
{
/**
* success response method.
*
* #param mixed $data The data resulting from the transaction
* #param string $message The success message of the transaction
* #param int $status The error code of the transaction, default is 200
*
* #return JsonResponse
*/
public function sendResponse( $data, string $message, int $status = 200 ) : JsonResponse
{
$response = [
'success' => true,
'data' => $data,
'message' => $message,
];
return response()->json( $response, $status );
}
/**
* return error response.
*
* #param string $message The error message
* #param mixed $data The list of errors of the transaction
* #param int $status The error code of the transaction, default is 404
*
* #return JsonResponse
*/
public function sendError( string $message, array $data = [], int $status = 404 ) : JsonResponse
{
$response = [
'success' => false,
'message' => $message,
];
if( !empty( $data ) ){
$response[ 'data' ] = $data;
}
return response()->json( $response, $status );
}
}
For example I can do this:
/**
* Display a listing of the resource.
*
* #return JsonResponse
*/
public function index() : JsonResponse
{
$users = User::all();
return $this->sendResponse( UserResource::collection( $users ), 'success' );
}
Now, in the other side, I have a project that consumes the API using Guzzle, so I have created a class that handles the requests:
namespace App\Models;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
class RequestURL
{
public string $endpoint;
public string $method;
public array $params;
public array $headers;
public mixed $response = null;
/**
* Constructor of the class
*
* #param string $endpoint
* #param string $method
* #param array $params
* #param array $headers
*/
public function __construct( string $endpoint, string $method = 'post', array $params = [], array $headers = [] )
{
$this->endpoint = $endpoint;
$this->method = $method;
$this->params = $params;
$this->headers = $this->makeHeaders( $headers );
$this->send();
}
/**
* Sends the request and expects the response from the api endpoint
*
* #return void
*/
private function send() : void
{
$client = new Client( [ 'base_uri' => config( 'superveci.api' ) ] );
try{
$this->response = $client->request( $this->method, $this->endpoint, [
'json' => $this->params,
'headers' => $this->headers,
'verify' => false,
] );
}
catch( GuzzleException $e ){
// TODO : log the error request
}
}
/**
* Returns the response on the requested url
*
* #return ResponseInterface|null
*/
public function getResponse() : ?ResponseInterface
{
return $this->response;
}
/**
* Returns the body of the response as a json object
*
* #return mixed
*/
public function getBody() : mixed
{
if( isset( $this->response ) ){
return json_decode( substr( (string) $this->getResponse()->getBody()->getContents(), 39 ) );
}
return null;
}
/**
* Returns the data from the response as a json object
*
* #return mixed
*/
public function getData() : mixed
{
return data_get( $this->getBody(), 'data' );
}
/**
* #return int
*/
public function getCode() : int
{
if( $this->response != null ){
return $this->response->getStatusCode();
}
return 401;
}
/**
* Sets the headers of the request up
*
* #param array $headers
*
* #return array
*/
private function makeHeaders( array $headers = [] ) : array
{
$bearer = ( isset( $headers[ 'token' ] ) ) ? $headers[ 'token' ] : request()->cookie( '_token' );
if( $bearer != null ){
$headers[ 'Authorization' ] = 'Bearer ' . $bearer;
}
return array_merge( [ 'Accept' => 'application/json', ], $headers );
}
}
As you can see, in the getBody() method, I wanted to cast the response data as an object, so, the logical thing here was to use json_decode. But for some reason it was returning null, until I found out that the response was dirty and I had to clean the first 39 characters of it, to be able to cast it using:
substr( (string) $this->getResponse()->getBody()->getContents(), 39 )
If I don' t do it, the response I get is similar to this (this is the resulting inspected code from my browser):
<pre hidden="">
{"success":true,"data":{"saludo":"Hello world","despedida":"Good bye cruel world"},"message":"success"}
</pre>
And of course the json_decode fails.
What is going on? Is this normal behavior? will it always be 39 characters?
Thanks
This is Laravel 8. I'm extending Illuminate\Mail\Transport\Transport class to create a custom mail transport in order to utilize the company's custom mail API with Illuminate\Mail\Mailable. I got most of it working, including file attachments, however the Swift_Mime_SimpleMimeEntity and the classes deriving from it contain getBody(), getFilename(), getSize(), and getContentType() but no methods to extract file extension.
<?php
namespace App\CustomMailDriver;
use GuzzleHttp\ClientInterface;
use Illuminate\Mail\Transport\Transport;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Swift_Mime_SimpleMessage;
class CustomTransport extends Transport
{
/**
* Guzzle client instance.
*
* #var \GuzzleHttp\ClientInterface
*/
protected $client;
/**
* API key.
*
* #var string
*/
protected $key;
/**
* The API URL to which to POST emails.
*
* #var string
*/
protected $url;
/**
* Create a new Custom transport instance.
*
* #param \GuzzleHttp\ClientInterface $client
* #param string|null $url
* #param string $key
* #return void
*/
public function __construct(ClientInterface $client, string $url, string $key)
{
$this->key = $key;
$this->client = $client;
$this->url = $url;
}
/**
* {#inheritdoc}
*/
public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
{
$this->beforeSendPerformed($message);
$payload = $this->getPayload($message);
try {
// ignore ssl (esp when working in DEV/QA)
$response = Http::withoutVerifying()->withHeaders([
'X-Authorization' => $this->key
])->post($this->url, $payload);
Log::info($response->body());
} catch (\Exception $e) {
Log::error($e->getMessage());
}
$this->sendPerformed($message);
return $this->numberOfRecipients($message);
}
/**
* Get the HTTP payload for sending the message.
*
* #param \Swift_Mime_SimpleMessage $message
* #return array
*/
protected function getPayload(Swift_Mime_SimpleMessage $message): array
{
// to
if (!empty($message->getTo())) {
$payload['payload']['to']['email'] = key($message->getTo());
}
// cc
if (!empty($message->getCc())) {
$payload['payload']['cc']['email'] = key($message->getCc());
}
// bcc
if (!empty($message->getBcc())) {
$payload['payload']['bcc']['email'] = key($message->getBcc());
}
// subject
$payload['payload']['subject'] = $message->getSubject();
// html
$payload['payload']['message']['html'] = $message->getBody();
// message children contains plain text, attachments, etc
$children = $message->getChildren();
if (!empty($children)) {
foreach($children as $child) {
// attachments
if (get_class($child) === 'Swift_Attachment') {
$payload['payload']['attachments'][] = [
'content' => base64_encode($child->getBody()),
'filename' => $child->getFilename(),
];
}
// plain text
if (get_class($child) === 'Swift_MimePart') {
$payload['payload']['message']['text'] = $child->getBody();
}
}
}
return $payload;
}
}
I had to go different route. Instead of searching the extension inside Transport class using Swift_Mime_SimpleMessage, I passed the filename with the original extension to Transport class from Illuminate\Mail\Mailable
public function build()
{
$tempUpload = request()->file('file_attachment');
$filename = $tampUpload->getClientOriginalName() . "." . $tempUpload->getClientOriginalExtension();
return $this->from($this->from_email, $this->from_name)
->subject('subject line')
->attach($tempUpload, ['as' => $filename)
->view('emails.gce.supplier_supplier')
->with($this->data);
}
I am working in Laravel 7 and have a middleware that checks if the user has a current user agreement, if not it redirects to a form that offers the current agreement. When the offer is accepted I need to redirect back to where they were originally going. I think I need to put something in the session so that when my controller stores their acceptance it can redirect back to the original route.
class VerifyAgreement
{
public function handle($request, Closure $next, $agreement)
{
if(UserAgreement::outOfDate($agreement)){
return redirect()->route('agreement.offer', $agreement);
}
return $next($request);
}
}
I think I need to get the current request and pass it to the redirect so the User Agreement controller can capture it somehow and then redirect once the agreement is stored... I am not sure.
class AgreementController extends Controller
{
public function offer(Agreement $agreement)
{
return view('agreement.offer',['agreement' => $agreement]);
}
public function agree(Request $request)
{
$agreement_uuid = App\Agreement::findOrFail($request->agreement)->uuid;
UserAgreement::create(['user_uuid'=>auth()->user()->uuid, 'agreement_uuid'=>$agreement_uuid]);
//redirect something something something
}
}
As mentioned in the comments by #Ruben Danielyan, the Illuminate\Routing\Redirector has some methods that you may find useful
Redirector.php
/**
* Create a new redirect response to the previously intended location.
*
* #param string $default
* #param int $status
* #param array $headers
* #param bool|null $secure
* #return \Illuminate\Http\RedirectResponse
*/
public function intended($default = '/', $status = 302, $headers = [], $secure = null)
{
$path = $this->session->pull('url.intended', $default);
return $this->to($path, $status, $headers, $secure);
}
/**
* Set the intended url.
*
* #param string $url
* #return void
*/
public function setIntendedUrl($url)
{
$this->session->put('url.intended', $url);
}
i need to send a copy of welcome email to specific mail.
what i did is i tried to create module to do it programmatically, i created a overrid that handle execute CreatePost.php but it sent before.
<?php
/**
* Copyright © Cinemanext, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Cinemanext\ForceLogin\Controller\Account;
use \Magento\Framework\App\ObjectManager;
/**
* #SuppressWarnings(PHPMD.TooManyFields)
* #SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CreatePost extends \Magento\Customer\Controller\Account\CreatePost
{
}
this option exist in order mail, you can send copy to specific email.
how i can add same function to welcome mail.
Try below code
<?php
namespace Cinemanext\ForceLogin\Controller\Account;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Customer\Model\CustomerFactory;
use Magento\Customer\Model\AddressFactory;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\Escaper;
use Magento\Framework\UrlFactory;
use Magento\Customer\Model\Session;
use Magento\Customer\Model\Registration;
use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Framework\App\ObjectManager;
class CreatePost extends \Magento\Framework\App\Action\Action
{
/**
* #var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
/**
* #var \Magento\Customer\Model\CustomerFactory
*/
protected $customerFactory;
/**
* #var \Magento\Customer\Model\AddressFactory
*/
protected $addressFactory;
/**
* #var \Magento\Framework\Message\ManagerInterface
*/
protected $messageManager;
/**
* #var \Magento\Framework\Escaper
*/
protected $escaper;
/**
* #var \Magento\Framework\UrlFactory
*/
protected $urlFactory;
/**
* #var \Magento\Customer\Model\Session
*/
protected $session;
/**
* #var Magento\Framework\Data\Form\FormKey\Validator
*/
private $formKeyValidator;
/**
* #param Context $context
* #param StoreManagerInterface $storeManager
* #param CustomerFactory $customerFactory
* #param AddressFactory $addressFactory
* #param ManagerInterface $messageManager
* #param Escaper $escaper
* #param UrlFactory $urlFactory
* #param Session $session
* #param Validator $formKeyValidator
*/
public function __construct(
Context $context,
StoreManagerInterface $storeManager,
CustomerFactory $customerFactory,
AddressFactory $addressFactory,
ManagerInterface $messageManager,
Escaper $escaper,
UrlFactory $urlFactory,
Session $session,
Validator $formKeyValidator = null
)
{
$this->storeManager = $storeManager;
$this->customerFactory = $customerFactory;
$this->addressFactory = $addressFactory;
$this->messageManager = $messageManager;
$this->escaper = $escaper;
$this->urlModel = $urlFactory->create();
$this->session = $session;
$this->formKeyValidator = $formKeyValidator ?: ObjectManager::getInstance()->get(Validator::class);
// messageManager can also be set via $context
// $this->messageManager = $context->getMessageManager();
parent::__construct($context);
}
/**
* Default customer account page
*
* #return void
*/
public function execute()
{
/** #var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
// if ($this->session->isLoggedIn() || !$this->registration->isAllowed()) {
// $resultRedirect->setPath('*/*/');
// return $resultRedirect;
// }
// check if the form is actually posted and has the proper form key
if (!$this->getRequest()->isPost() || !$this->formKeyValidator->validate($this->getRequest())) {
$url = $this->urlModel->getUrl('*/*/create', ['_secure' => true]);
$resultRedirect->setUrl($this->_redirect->error($url));
return $resultRedirect;
}
$websiteId = $this->storeManager->getWebsite()->getWebsiteId();
$firstName = 'John';
$lastName = 'Doe';
$email = 'johndoe4#example.com';
$password = 'Test1234';
// instantiate customer object
$customer = $this->customerFactory->create();
$customer->setWebsiteId($websiteId);
// check if customer is already present
// if customer is already present, then show error message
// else create new customer
if ($customer->loadByEmail($email)->getId()) {
//echo 'Customer with the email ' . $email . ' is already registered.';
$message = __(
'There is already an account with this email address "%1".',
$email
);
// #codingStandardsIgnoreEnd
$this->messageManager->addError($message);
} else {
try {
// prepare customer data
$customer->setEmail($email);
$customer->setFirstname($firstName);
$customer->setLastname($lastName);
// set null to auto-generate password
$customer->setPassword($password);
// set the customer as confirmed
// this is optional
// comment out this line if you want to send confirmation email
// to customer before finalizing his/her account creation
$customer->setForceConfirmed(true);
// save data
$customer->save();
// save customer address
// this is optional
// you can skip saving customer address while creating the customer
$customerAddress = $this->addressFactory->create();
$customerAddress->setCustomerId($customer->getId())
->setFirstname($firstName)
->setLastname($lastName)
->setCountryId('US')
->setRegionId('12') // optional, depends upon Country, e.g. USA
->setRegion('California') // optional, depends upon Country, e.g. USA
->setPostcode('90232')
->setCity('Culver City')
->setTelephone('888-888-8888')
->setFax('999')
->setCompany('XYZ')
->setStreet(array(
'0' => 'Your Customer Address 1', // compulsory
'1' => 'Your Customer Address 2' // optional
))
->setIsDefaultBilling('1')
->setIsDefaultShipping('1')
->setSaveInAddressBook('1');
try {
// save customer address
$customerAddress->save();
} catch (Exception $e) {
$this->messageManager->addException($e, __('We can\'t save the customer address.'));
}
// send welcome email to the customer
$customer->sendNewAccountEmail();
//echo 'Customer with the email ' . $email . ' is successfully created.';
$this->messageManager->addSuccess(
__(
'Customer account with email %1 created successfully.',
$email
)
);
$url = $this->urlModel->getUrl('*/*/create', ['_secure' => true]);
$resultRedirect->setUrl($this->_redirect->success($url));
//$resultRedirect->setPath('*/*/');
return $resultRedirect;
} catch (StateException $e) {
$url = $this->urlModel->getUrl('customer/account/forgotpassword');
// #codingStandardsIgnoreStart
$message = __(
'There is already an account with this email address. If you are sure that it is your email address, click here to get your password and access your account.',
$url
);
// #codingStandardsIgnoreEnd
$this->messageManager->addError($message);
} catch (InputException $e) {
$this->messageManager->addError($this->escaper->escapeHtml($e->getMessage()));
foreach ($e->getErrors() as $error) {
$this->messageManager->addError($this->escaper->escapeHtml($error->getMessage()));
}
} catch (LocalizedException $e) {
$this->messageManager->addError($this->escaper->escapeHtml($e->getMessage()));
} catch (\Exception $e) {
$this->messageManager->addException($e, __('We can\'t save the customer.'));
}
}
$this->session->setCustomerFormData($this->getRequest()->getPostValue());
$defaultUrl = $this->urlModel->getUrl('*/*/create', ['_secure' => true]);
$resultRedirect->setUrl($this->_redirect->error($defaultUrl));
return $resultRedirect;
}
}
I am very new to testing, but have now found it essential to automate my testing.
I have a test that is working fine up until it gets to the link '/cart' it gets to the link '/cart' no problem, but any other link I try to click afterwards always ends up back at the cart.
here is my error after trying to navigate away from the cart.
Failed asserting that two strings are equal.
--- Expected
+++ Actual
## ##
-'http://ngwenya-mtb.dev/events'
+'http://ngwenya-mtb.dev/cart'
And here is my test script
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase {
//use Illuminate\Foundation\Testing\WithoutMiddleware;
//use DatabaseTransactions;
//use withoutMiddleware;
//use DatabaseMigrations;
/**
*
* A basic functional test example.
* Please choose a unique email address for your new participant
* #return void
*/
public function testNewUserRegistration() {
$this->visit('http://ngwenya-mtb.dev/')
// View Event
->click('View event details')
->seePageIs('/event?id=30')
->click('#enter-race47')
->press('Enter yourself to this race')
->seePageIs('/events/courses/register/addtocart')
//->withSession(['This email is already registered' => 'alert-danger'])
/////////////////////////////////////////////
// Fill the register for for new user
/////////////////////////////////////////////
->type('Bingo', 'first_name')
->type('11111111', 'password')
->type('11111111', 'password_confirmation')
->type(''.substr(md5(time()), 0, 12).'#tesing.com', 'email')
//->check('terms')
->select('Male', 'gender')
->select('1985', 'year')
->select('07', 'month')
->select('21', 'day')
->select('Small', 'shirt_size')
->select('Swaziland ID', 'id_type')
->type('badassnumber', 'id_number')
->select('Swazi', 'nationality')
//Contact details Physical
->type('Dawlish', 'town_physical')
->select('Swaziland', 'country_physical')
->type('864741', 'phone_cell')
//Emergency contact details 1
->type('Simon', 'emergency_contact_1')
->type('Brother', 'emergency_relationship_1')
->type('864741', 'emergency_phone_1');
$this->press('Register');
$this->seePageIs('/cart');
/////////////////////////////////////////////
// Add a new user
/////////////////////////////////////////////
$this->visit('http://ngwenya-mtb.dev/');
$this->click('#events-link')
->seePageIs('/events');
dd($this->response->getContent());exit;
$this->click('#event-30');
$this->seePageIs('/event?id=30');
$this->click('#enter-race48');
$this->press('Enter someone else to this race');
$this->seePageIs('/events/courses/register/addtocart');
}
}
Everything is working fine up until this comment
/////////////////////////////////////////////
// Add a new user
/////////////////////////////////////////////
Here is my Registration controller
<?php
namespace App\Http\Controllers;
use Vinkla\Hashids\HashidsManager;
use Illuminate\Routing\Controller as BaseController;
use Sentinel\FormRequests\RegisterRequest;
use Sentinel\FormRequests\EmailRequest;
use Sentinel\FormRequests\ResetPasswordRequest;
use Sentinel\Repositories\Group\SentinelGroupRepositoryInterface;
use Sentinel\Repositories\User\SentinelUserRepositoryInterface;
use Sentinel\Traits\SentinelRedirectionTrait;
use Sentinel\Traits\SentinelViewfinderTrait;
use Sentry;
use View;
use Request;
use Event;
use Redirect;
use Session;
use Config;
use App\Models\Users;
use Illuminate\Support\Facades\Input;
use Gloudemans\Shoppingcart\Facades\Cart;
class RegistrationController extends BaseController
{
/**
* Traits
*/
use SentinelRedirectionTrait;
use SentinelViewfinderTrait;
/**
* Constructor
*/
public function __construct(
SentinelUserRepositoryInterface $userRepository,
SentinelGroupRepositoryInterface $groupRepository,
HashidsManager $hashids
) {
$this->userRepository = $userRepository;
$this->groupRepository = $groupRepository;
$this->hashids = $hashids;
}
/**
* Show the registration form, if registration is allowed
*
* #return Response
*/
public function registration()
{
// Is this user already signed in? If so redirect to the post login route
if (Sentry::check()) {
return $this->redirectTo('session_store');
}
//If registration is currently disabled, show a message and redirect home.
if (! config('sentinel.registration', false)) {
return $this->redirectTo(['route' => 'home'], ['error' => trans('Sentinel::users.inactive_reg')]);
}
// All clear - show the registration form.
return $this->viewFinder(config('sentinel.view.user_register', 'Sentinel::users.register'));
}
/**
* Process a registration request
*
* #return Response
*/
public function register(RegisterRequest $request)
{
// Gather input
$data = $request->all();
// collect cart items
$email = Input::get('email');
$course_id = Input::get('course_id');
$event_name = Input::get('event_name');
$entry_fee = Input::get('entry_fee');
// check user exists
if (Users::where('email', '=', $email)->exists()) {
// user found
$request->session()->flash('alert-danger', 'Warning: This email is already registered.');
Input::flash();
return View::make('sentinel.users.register')
->with('course_id',$course_id)
->with('event_name',$event_name)
->with('entry_fee',$entry_fee);
}
// Add user and course to cart
if ($course_id) {
$firstUserRowId = Cart::add($course_id, $event_name , 1, $entry_fee, [
'first_name' => Input::get('first_name'),
'last_name' => Input::get('last_name'),
'email' => Input::get('email'),
'no_email' => 0,
'master_user' => 1,
'gender' => Input::get('gender'),
'dob' => Input::get('dob'),
'shirt_size' => Input::get('shirt_size'),
'id_type' => Input::get('id_type'),
'id_number' => Input::get('id_number'),
'nationality' => Input::get('nationality'),
'phone_cell' => Input::get('phone_cell'),
'town_physical' => Input::get('town_physical'),
'country_physical' => Input::get('country_physical'),
'emergency_contact_1' => Input::get('emergency_contact_1'),
'emergency_relationship_1' => Input::get('emergency_relationship_1'),
'emergency_phone_1' => Input::get('emergency_phone_1'),
]);
}
// get email from request
$email = $request->only('email');
foreach ($email as $userModel) {}
// Edit date of birth from request
$year = Input::get('year');
$month = Input::get('month');
$day = Input::get('day');
$dob = $year.'-'.$month.'-'.$day;
$data['dob'] = $dob;
// Attempt Registration
$result = $this->userRepository->store($data);
// Log user in
FunctionsController::loginUser($userModel);
// It worked! Use config to determine where we should go.
return $this->redirectViaResponse('registration_complete', $result);
}
/**
* Activate a new user
*
* #param int $id
* #param string $code
*
* #return Response
*/
public function activate($hash, $code)
{
// Decode the hashid
$id = $this->hashids->decode($hash)[0];
// Attempt the activation
$result = $this->userRepository->activate($id, $code);
// It worked! Use config to determine where we should go.
return $this->redirectViaResponse('registration_activated', $result);
}
/**
* Show the 'Resend Activation' form
*
* #return View
*/
public function resendActivationForm()
{
return $this->viewFinder('Sentinel::users.resend');
}
/**
* Process resend activation request
* #return Response
*/
public function resendActivation(EmailRequest $request)
{
// Resend the activation email
$result = $this->userRepository->resend(['email' => e($request->get('email'))]);
// It worked! Use config to determine where we should go.
return $this->redirectViaResponse('registration_resend', $result);
}
/**
* Display the "Forgot Password" form
*
* #return \Illuminate\View\View
*/
public function forgotPasswordForm()
{
return $this->viewFinder('Sentinel::users.forgot');
}
/**
* Process Forgot Password request
* #return Response
*/
public function sendResetPasswordEmail(EmailRequest $request)
{
// Send Password Reset Email
$result = $this->userRepository->triggerPasswordReset(e($request->get('email')));
// It worked! Use config to determine where we should go.
return $this->redirectViaResponse('registration_reset_triggered', $result);
}
/**
* A user is attempting to reset their password
*
* #param $id
* #param $code
*
* #return Redirect|View
*/
public function passwordResetForm($hash, $code)
{
// Decode the hashid
$id = $this->hashids->decode($hash)[0];
// Validate Reset Code
$result = $this->userRepository->validateResetCode($id, $code);
if (! $result->isSuccessful()) {
return $this->redirectViaResponse('registration_reset_invalid', $result);
}
return $this->viewFinder('Sentinel::users.reset', [
'hash' => $hash,
'code' => $code
]);
}
/**
* Process a password reset form submission
*
* #param $hash
* #param $code
* #return Response
*/
public function resetPassword(ResetPasswordRequest $request, $hash, $code)
{
// Decode the hashid
$id = $this->hashids->decode($hash)[0];
// Gather input data
$data = $request->only('password', 'password_confirmation');
// Change the user's password
$result = $this->userRepository->resetPassword($id, $code, e($data['password']));
// It worked! Use config to determine where we should go.
return $this->redirectViaResponse('registration_reset_complete', $result);
}
}
It seems that when you click and a your link "Register" your redirection fail, so check if you have multiple "Register" links/buttons, and if they are pointing to the right URL
And for easiest debugging, you should make less assertions per Test, you will gain in visibility :)