walletMobileNumber = $walletMobileNumber; return $this; } public function getWalletMobileNumber() { return $this->walletMobileNumber; } public function setPublicKey($publicKey) { $this->publicKey = $publicKey; return $this; } public function getPublicKey() { return $this->publicKey; } public function setSecretKey($secretKay) { $this->secretKay = $secretKay; return $this; } public function getSecretKey() { return $this->secretKay; } public function setIframeId($iframeId) { $this->iframeId = $iframeId; return $this; } public function getIframeId() { return $this->iframeId; } public function setGatewayType($gatewayType) { $this->gatewayType = $gatewayType; return $this; } public function getGatewayType() { return $this->gatewayType; } public function setApiKey($apiKey) { $this->apiKey = $apiKey; return $this; } public function getApiKey() { return $this->apiKey; } public function setHmacSecret($hmacSecret) { $this->hmacSecret = $hmacSecret; return $this; } public function getHmacSecret() { return $this->hmacSecret; } public function setIntegrationId($integrationId) { $this->integrationId = $integrationId; return $this; } public function getIntegrationId() { return $this->integrationId; } /* * charge_amount(); * @required param list * $amount * * * */ public function charge_amount($amount) { if (in_array($this->getCurrency(), $this->supported_currency_list())) { return $amount * 100; } return $this->get_amount_in_usd($amount) * 100; } /** * @required param list * $args['amount'] * $args['description'] * $args['item_name'] * $args['ipn_url'] * $args['cancel_url'] * $args['payment_track'] * return redirect url for * */ public function charge_customer($args) { $authorize_token = $this->authentication_request(); /* make eCommerce Order */ $order_request = $this->order_registration_request($authorize_token,$args); /* work on payment key request */ $payment_key_request_token = $this->payment_key_request($authorize_token,$args,($order_request['order_id'] ?? "")); $payment_url = ''; /** Available Gateway Type * "accept-online" //card payment "accept-kiosk" "accept-wallet" "accept-valu" "accept-installments" "accept-sympl" "accept-premium" "accept-souhoola" "accept-shahry" "accept-get_go" "accept-lucky" "accept-forsa" "accept-tabby" "accept-nowpay" * */ /* get payment page url based on the payment gateway type */ if ($this->getGatewayType() === 'accept-online'){ $payment_url = 'https://accept.paymobsolutions.com/api/acceptance/iframes/'.$this->getIframeId().'?payment_token='.$payment_key_request_token; }elseif ($this->getGatewayType() === 'accept-valu'){ /* iframe id should be fore valU */ $payment_url = 'https://accept.paymobsolutions.com/api/acceptance/iframes/'.$this->getIframeId().'?payment_token='.$payment_key_request_token; }elseif ($this->getGatewayType() === 'accept-kiosk'){ // api request for kiosk, need to show bill_reference to the user for pay it from koisok $bill_reference = $this->process_kiosk_payment_request($payment_key_request_token,$authorize_token,$args); return "your kiosk payment bill reference id:". $bill_reference; }elseif ($this->getGatewayType() === 'accept-wallet'){ //todo:: call wallet api and redirect them to redirect_url $redirect_url = $this->process_wallet_payment_request($payment_key_request_token,$authorize_token,$args); return redirect()->away($redirect_url); } return view('paymentgateway::paymob',[ "payment_url" => $payment_url ]); } /** * @required param list * $args['request'] * $args['cancel_url'] * $args['success_url'] * * return @void * */ public function ipn_response($args = []) { $request = request(); //todo:: need to check it is is post or get request, //post request mean == transaction process callback //get request mean == transaction response callback //todo:: need to verify hmac $request_method = strtolower($request->method()); $hmac_type = $request_method === 'get' ? 'TRANSACTION' : 'TRANSACTION'; $hash_value = $this->getHasvalue(); $order_id = request()->get('merchant_order_id'); $callback_type = 'TRANSACTION'; if (strtolower(request()->method()) === 'post') { $callback_type = request()->type; } if(hash_equals($hash_value,$request->hmac)){ if ($request_method === 'post'){ //handle post request if ($callback_type == 'TRANSACTION') { if ( $request->success === true && $request->is_voided === false && $request->is_refunded === false && $request->pending === false && $request->is_void === false && $request->is_refund === false && $request->error_occured === false ) { return $this->verified_data([ 'status' => 'processing', 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } else if ( $request->success === true && $request->is_refunded === true && $request->is_voided === false && $request->pending === false && $request->is_void === false && $request->is_refund === false ) { return $this->verified_data([ 'status' => 'refunded', 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } else if ( $request->success === true && $request->is_voided === true && $request->is_refunded === false && $request->pending === false && $request->is_void === false && $request->is_refund === false ) { return $this->verified_data([ 'status' => 'cancelled', 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } else if ( $request->success === false && $request->is_voided === false && $request->is_refunded === false && $request->is_void === false && $request->is_refund === false ) { return $this->verified_data([ 'status' => 'pending-payment', 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } }else if ($callback_type == 'TOKEN'){ //handle if token accept } }elseif ($request_method === 'get'){ //handle get request if ( $request->success === "true" && $request->is_voided === "false" && $request->is_refunded === "false" && $request->pending === "false" && $request->is_void === "false" && $request->is_refund === "false" && $request->error_occured === "false" ) { return $this->verified_data([ 'status' => 'complete', 'transaction_id' => request()->get('id'), 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } elseif($request->data_message ==="Approved" ) { return $this->verified_data([ 'status' => 'complete', 'transaction_id' => request()->get('id'), 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } } } return $this->verified_data([ 'status' => 'failed', 'order_id' => PaymentGatewayHelpers::unwrapped_id($order_id), 'order_type' => null ]); } /** * geteway_name(); * return @string * */ public function gateway_name() { return 'paymob'; } /** * charge_currency(); * return @string * */ public function charge_currency() { if (in_array($this->getCurrency(), $this->supported_currency_list())) { return $this->getCurrency(); } return "EGP"; } /** * supported_currency_list(); * it will returl all of supported currency for the payment gateway * return array * */ public function supported_currency_list() { $supported_currency = ['EGP']; if ($this->getGatewayType() === "accept-online"){ $supported_currency = ['EGP', 'USD', 'EUR', 'GBP']; } return $supported_currency; } private function base_api_url() { return 'https://accept.paymob.com/api/'; } private function authentication_request() { $url = $this->base_api_url().'auth/tokens'; //todo:: post request $response = Http::post($url,[ "api_key" => $this->getApiKey() ]); if ($response->status() === 201){ $result = $response->object(); $authorise_token = $result->token; if(!empty($authorise_token)){ return $authorise_token; } abort(500,'authentication request token generate failed'); } abort(500,'authentication_request failed'); } private function order_registration_request($authorize_token,$args) { $response = Http::post($this->base_api_url().'ecommerce/orders',[ "auth_token" => $authorize_token, "delivery_needed" => "false", "amount_cents" => $this->charge_amount($args['amount']), "currency" => $this->getCurrency(), "merchant_order_id" => PaymentGatewayHelpers::wrapped_id($args['order_id']), "items" => [ [ "name" => $args['title'], "amount_cents" => $this->charge_amount($args['amount']), "description" => $args['description'], "quantity" => "1" ] ] ]); if($response->status() === 201){ return [ 'order_id' => $response->object()?->id, 'token' => $response->object()?->token ]; } abort(500,'order_registration_request failed'); } private function payment_key_request($authorize_token, array $args,$order_request_id) { $response = Http::post($this->base_api_url().'acceptance/payment_keys',[ "auth_token" => $authorize_token, "amount_cents" => $this->charge_amount($args['amount']), "expiration" => 3600, "order_id" => $order_request_id, "billing_data" => [ "first_name" => "Clifford", "last_name" => "Nicolas", "email" => "claudette09@exa.com", "phone_number" => "+86(8)9135210487", "apartment" => "NA", "floor" => "NA", "street" => "NA", "building" => "NA", "shipping_method" => "NA", "postal_code" => "NA", "city" => "NA", "country" => "NA", "state" => "NA" ], "currency" => $this->getCurrency(), "integration_id" => $this->getIntegrationId(), "lock_order_when_paid" => "false" ]); if($response->status() === 201){ return $response->object()?->token; } abort(500,'payment_key_request failed'); } private function process_kiosk_payment_request($payment_key_request_token,$authorize_token,$args) { //todo api request $response = Http::asJson()->post($this->base_api_url().'acceptance/payment_keys',[ "payment_token" => $payment_key_request_token, "auth_token" => $authorize_token, "source" => [ "identifier" => "AGGREGATOR", "subtype" => "AGGREGATOR" ], 'amount_cents' => $this->charge_amount($args['amount']), 'currency' => $this->getCurrency() ]); if($response->status() === 201){ return $response->object()?->data?->bill_reference; } abort(500,'process_kiosk_payment_request bill_reference generate failed'); } private function process_wallet_payment_request($payment_key_request_token,$authorize_token,$args) { //todo api request $response = Http::asJson()->post($this->base_api_url().'acceptance/payment_keys',[ "payment_token" => $payment_key_request_token, "auth_token" => $authorize_token, "source" => [ "identifier" => $this->getWalletMobileNumber(), "subtype" => "WALLET" ], 'amount_cents' => $this->charge_amount($args['amount']), 'currency' => $this->getCurrency() ]); if($response->status() === 201){ return $response->object()->redirect_url; } abort(500,'process_wallet_payment_request redirect_url generate failed'); } private function getHmacStringArray() { $return_string = request()->all(); if (strtolower(request()->method()) === 'post'){ $return_string = ''; $callback_type = request()->type; $object = request()->obj; $return_string = request()->obj; if ($callback_type === 'TRANSACTION'){ $return_string->order = $object->order?->id; $return_string->order = $object->order?->id; $return_string->is_3d_secure = ($object->is_3d_secure === true) ? 'true' : 'false'; $return_string->is_auth = ($object->is_auth === true) ? 'true' : 'false'; $return_string->is_capture = ($object->is_capture === true) ? 'true' : 'false'; $return_string->is_refunded = ($object->is_refunded === true) ? 'true' : 'false'; $return_string->is_standalone_payment = ($object->is_standalone_payment === true) ? 'true' : 'false'; $return_string->is_voided = ($object->is_voided === true) ? 'true' : 'false'; $return_string->success = ($object->success === true) ? 'true' : 'false'; $return_string->error_occured = ($object->error_occured === true) ? 'true' : 'false'; $return_string->has_parent_transaction = ($object->has_parent_transaction === true) ? 'true' : 'false'; $return_string->pending = ($object->pending === true) ? 'true' : 'false'; $return_string->source_data_pan = $object->source_data?->pan; $return_string->source_data_type = $object->source_data?->type; $return_string->source_data_sub_type = $object->source_data?->sub_type; /* amount_cents created_at currency error_occured has_parent_transaction id integration_id is_3d_secure is_auth is_capture is_refunded is_standalone_payment is_voided order.id owner pending source_data.pan source_data.sub_type source_data.type success */ }elseif ($callback_type === 'DELIVERY_STATUS'){ $return_string->order = $object->order?->id; } }elseif(strtolower(request()->method()) === 'get'){ //handle if the callback if get request transaction callback. $callback_type = 'TRANSACTION'; $return_string = request()->all(); } return $return_string; } private function getHasvalue() { $callback_type = 'TRANSACTION'; if (strtolower(request()->method()) === 'post') { $callback_type = request()->type; } $hmac_string = $this->getHmacStringArray(); $str = ''; switch ($callback_type) { case 'TRANSACTION': $str = $hmac_string['amount_cents'] . $hmac_string['created_at'] . $hmac_string['currency'] . $hmac_string['error_occured'] . $hmac_string['has_parent_transaction'] . $hmac_string['id'] . $hmac_string['integration_id'] . $hmac_string['is_3d_secure'] . $hmac_string['is_auth'] . $hmac_string['is_capture'] . $hmac_string['is_refunded'] . $hmac_string['is_standalone_payment'] . $hmac_string['is_voided'] . $hmac_string['order'] . $hmac_string['owner'] . $hmac_string['pending'] . $hmac_string['source_data_pan'] . $hmac_string['source_data_sub_type'] . $hmac_string['source_data_type'] . $hmac_string['success']; break; case 'TOKEN': $str = $hmac_string['card_subtype'] . $hmac_string['created_at'] . $hmac_string['email'] . $hmac_string['id'] . $hmac_string['masked_pan'] . $hmac_string['merchant_id'] . $hmac_string['order_id'] . $hmac_string['token']; break; case 'DELIVERY_STATUS': $str = $hmac_string['created_at'] . $hmac_string['extra_description'] . $hmac_string['gps_lat'] . $hmac_string['gps_long'] . $hmac_string['id'] . $hmac_string['merchant'] . $hmac_string['order'] . $hmac_string['status']; break; } $hash = hash_hmac('sha512', $str, $this->getHmacSecret()); return $hash; } }