diff --git a/README.md b/README.md index d0966d0..d724922 100755 --- a/README.md +++ b/README.md @@ -1,68 +1,12 @@ # USSD Code Challenge: SwahiliPot Developer Community -## Due: 30th July,2018 or Earlier -#### This code challenge is due on the 30th of July,2018 or earlier. +## By Johnes Mecha -## Simple Unchanging Rules -The code challenge is and will always be judged using the following criteria - - A Correct fork, branch and pull request - - Using the GitHub Pull Request Time Stamp and correct code quality & structure, the first developer whose code runs successfully on the sandbox/simulator wins - - Other developers who submit successfully MAY also get rewarded with secondary items - - Code quality and structure will be evaluated - - The order for pull requests will be followed, first come first win basis! - - Do not share any code that you cannot opensource on the Git Repository as its open source and Africa's Talking will not be liable for any breach of intellectual property (if any) once shared on the platform. +## How to access the Code +Go to the AfricaStalking Simulator and under ussd section and type -## Terms and Conditions -You can participate on as many challenges as you wish: - - Everyone can participate for secondary prizes, just ensure that you create your branch with your international format phone number. Airtime rewards will only go to countries we have AirTime APIs in. - - Africa's Talking reserves the right to announce the winners - - Africa's Talking reserves the right to reward the winners based on Africa's Talking Criterion - - Do not share any code that you cannot opensource on the Git Repository as its open source and Africa's Talking will not be liable for any breach of intellectual property (if any) once shared on the platform. - - Code Challenges are time bound - the time restriction is specified on the challenge - - Additional rules MAY be provided on the code challenge and will vary for each challenge - - You are free to use all manner of tools - - Successive interviews for projects MAY be run to satisfy participating Africa's Talking Partners +## Dial \*384\*545454# + -## Code Challenge Bounty: - - First Prizes: KES 10,000 cash prize - - Secondary Prizes: Airtime for successful pull requests before or on 30th July, 2018 -## Task -In this code challenge you will be required to make a USSD application that implements: -1. Mobile checkout with MPESA -2. Ability to send Airtime -3. SMS alert confirming airtime sent - -### Task Workflow: -1. User initiates USSD code -2. User selects from the menu which should contain - 1. Mobile checkout - 2. Send airtime option -3. If the user selects the mobile checkout, they should be able to pay via MPESA -4. If the user selects the send airtime option, they should be able to add how much they want to send and recieve an SMS that confirms airtime has been sent. - -### Additional: -1. See the online version of the code challenge [here](http://atdevoutreach.viewdocs.io/CodeChallengeSwahiliPot/CodeChallengeSwahiliPot/) to get acquainted. - -2. Check out the format for submitting your code [here](http://atdevoutreach.viewdocs.io/CodeChallengeSwahiliPot/CodeChallengeSteps/) - -## Resources -You can use the following resources to get you started on your way: -* [Starting on the Sandbox and Simulator](http://help.africastalking.com/website/how-to-get-started-on-the-africas-talking-sand-box) -* [Africas Talking's Python SDK documentation on GitHub](https://github.com/AfricasTalkingLtd/africastalking-python) -* [USSD Documentation](http://docs.africastalking.com/ussd) -* [Airtime Sending Documentation](http://docs.africastalking.com/airtime/sending) -* [Lizz's Article on building a USSD application](https://docs.google.com/document/d/1ouYo5tRRHPJ39PUx0vFqn97HXd4-6V3X0plcfRaqAOI/edit?usp=sharing) -* [SMS Sending Documentation](http://docs.africastalking.com/sms/sending) -* [SMS Receiving Documentation](http://docs.africastalking.com/sms/callback) -* [Other Help articles](http://help.africastalking.com/sms) -- More on [Logging in, Signing up/Registration, Verifying/Activating your account, Managing Teams and applications](http://help.africastalking.com/website) -- Videos on getting started [on the Africa's Talking Sandbox](https://www.dropbox.com/sh/qq086503d5zaq7l/AADEo-oazNF_PgYIPRjPpeCua?dl=0) - - -## About Africa's Talking Code Challenges -Please read the overview for all code challenges [here.](http://atdevoutreach.viewdocs.io/CodeChallengeSwahiliPot/) - -## Get Support on the Africa's Talking Slack -In case you have any questions, join our Slack [here](https://slackin-africastalking.now.sh/) diff --git a/code/AfricasTalkingGateway.php b/code/AfricasTalkingGateway.php new file mode 100644 index 0000000..ddf7efa --- /dev/null +++ b/code/AfricasTalkingGateway.php @@ -0,0 +1,626 @@ + + + AFRICAStALKING SMS GATEWAY CLASS IS A FREE SOFTWARE IE. CAN BE MODIFIED AND/OR REDISTRIBUTED + UNDER THE TERMS OF GNU GENERAL PUBLIC LICENCES AS PUBLISHED BY THE + FREE SOFTWARE FOUNDATION VERSION 3 OR ANY LATER VERSION + + THE CLASS IS DISTRIBUTED ON 'AS IS' BASIS WITHOUT ANY WARRANTY, INCLUDING BUT NOT LIMITED TO + THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +class AfricasTalkingGatewayException extends Exception {} + +class AfricasTalkingGateway +{ + protected $_username; + protected $_apiKey; + + protected $_requestBody; + protected $_requestUrl; + + protected $_responseBody; + protected $_responseInfo; + + //Turn this on if you run into problems. It will print the raw HTTP response from our server + const Debug = false; + + const HTTP_CODE_OK = 200; + const HTTP_CODE_CREATED = 201; + + public function __construct($username_, $apiKey_) + { + $this->_username = $username_; + $this->_apiKey = $apiKey_; + + if ($username_ === 'sandbox') { + $this->_environment = 'sandbox'; + } else { + $this->_environment = 'production'; + } + + $this->_requestBody = null; + $this->_requestUrl = null; + + $this->_responseBody = null; + $this->_responseInfo = null; + } + + + //Messaging methods + public function sendMessage($to_, $message_, $from_ = null, $bulkSMSMode_ = 1, Array $options_ = array()) + { + if ( strlen($to_) == 0 || strlen($message_) == 0 ) { + throw new AfricasTalkingGatewayException('Please supply both to and message parameters'); + } + + $params = array( + 'username' => $this->_username, + 'to' => $to_, + 'message' => $message_, + ); + + if ( $from_ !== null ) { + $params['from'] = $from_; + $params['bulkSMSMode'] = $bulkSMSMode_; + } + + //This contains a list of parameters that can be passed in $options_ parameter + if ( count($options_) > 0 ) { + $allowedKeys = array ( + 'enqueue', + 'keyword', + 'linkId', + 'retryDurationInHours' + ); + + //Check whether data has been passed in options_ parameter + foreach ( $options_ as $key => $value ) { + if ( in_array($key, $allowedKeys) && strlen($value) > 0 ) { + $params[$key] = $value; + } else { + throw new AfricasTalkingGatewayException("Invalid key in options array: [$key]"); + } + } + } + + $this->_requestUrl = $this->getSendSmsUrl(); + $this->_requestBody = http_build_query($params, '', '&'); + + $this->executePOST(); + + if ( $this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED ) { + $responseObject = json_decode($this->_responseBody); + if(count($responseObject->SMSMessageData->Recipients) > 0) + return $responseObject->SMSMessageData->Recipients; + + throw new AfricasTalkingGatewayException($responseObject->SMSMessageData->Message); + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + + public function fetchMessages($lastReceivedId_) + { + $username = $this->_username; + $this->_requestUrl = $this->getSendSmsUrl().'?username='.$username.'&lastReceivedId='. intval($lastReceivedId_); + + $this->executeGet(); + + if ( $this->_responseInfo['http_code'] == self::HTTP_CODE_OK ) { + $responseObject = json_decode($this->_responseBody); + return $responseObject->SMSMessageData->Messages; + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + + //Subscription methods + public function createSubscription($phoneNumber_, $shortCode_, $keyword_, $checkoutToken_) + { + + if ( strlen($phoneNumber_) == 0 || strlen($shortCode_) == 0 || strlen($keyword_) == 0 || strlen($checkoutToken_) == 0 ) { + throw new AfricasTalkingGatewayException('Please supply phoneNumber, shortCode, keyword and checkoutToken'); + } + + $params = array( + 'username' => $this->_username, + 'phoneNumber' => $phoneNumber_, + 'shortCode' => $shortCode_, + 'keyword' => $keyword_, + 'checkoutToken' => $checkoutToken_, + ); + + $this->_requestUrl = $this->getSubscriptionUrl("/create"); + $this->_requestBody = http_build_query($params, '', '&'); + + $this->executePOST(); + + if ( $this->_responseInfo['http_code'] != self::HTTP_CODE_CREATED ) + throw new AfricasTalkingGatewayException($this->_responseBody); + + return json_decode($this->_responseBody); + } + + public function deleteSubscription($phoneNumber_, $shortCode_, $keyword_) + { + if ( strlen($phoneNumber_) == 0 || strlen($shortCode_) == 0 || strlen($keyword_) == 0 ) { + throw new AfricasTalkingGatewayException('Please supply phoneNumber, shortCode and keyword'); + } + + $params = array( + 'username' => $this->_username, + 'phoneNumber' => $phoneNumber_, + 'shortCode' => $shortCode_, + 'keyword' => $keyword_ + ); + + $this->_requestUrl = $this->getSubscriptionUrl("/delete"); + $this->_requestBody = http_build_query($params, '', '&'); + + $this->executePOST(); + + if ( $this->_responseInfo['http_code'] != self::HTTP_CODE_CREATED ) + throw new AfricasTalkingGatewayException($this->_responseBody); + + return json_decode($this->_responseBody); + + } + + public function fetchPremiumSubscriptions($shortCode_, $keyword_, $lastReceivedId_ = 0) + { + $params = '?username='.$this->_username.'&shortCode='.$shortCode_; + $params .= '&keyword='.$keyword_.'&lastReceivedId='.intval($lastReceivedId_); + $this->_requestUrl = $this->getSubscriptionUrl($params); + + $this->executeGet(); + + if ( $this->_responseInfo['http_code'] == self::HTTP_CODE_OK ) { + $responseObject = json_decode($this->_responseBody); + return $responseObject->responses; + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + + //Call methods + public function call($from_, $to_) + { + if ( strlen($from_) == 0 || strlen($to_) == 0 ) { + throw new AfricasTalkingGatewayException('Please supply both from and to parameters'); + } + + $params = array( + 'username' => $this->_username, + 'from' => $from_, + 'to' => $to_ + ); + + $this->_requestUrl = $this->getVoiceUrl() . "/call"; + $this->_requestBody = http_build_query($params, '', '&'); + + $this->executePOST(); + + if(($responseObject = json_decode($this->_responseBody)) !== null) { + if(strtoupper(trim($responseObject->errorMessage)) == "NONE") { + return $responseObject->entries; + } + throw new AfricasTalkingGatewayException($responseObject->errorMessage); + } + else + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function getNumQueuedCalls($phoneNumber_, $queueName = null) + { + $this->_requestUrl = $this->getVoiceUrl() . "/queueStatus"; + $params = array( + "username" => $this->_username, + "phoneNumbers" => $phoneNumber_ + ); + if($queueName !== null) + $params['queueName'] = $queueName; + $this->_requestBody = http_build_query($params, '', '&'); + $this->executePOST(); + + if(($responseObject = json_decode($this->_responseBody)) !== null) { + if(strtoupper(trim($responseObject->errorMessage)) == "NONE") + return $responseObject->entries; + throw new AfricasTalkingGatewayException($responseObject->ErrorMessage); + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + + public function uploadMediaFile($url_, $phoneNumber_) + { + $params = array( + "username" => $this->_username, + "url" => $url_, + "phoneNumber" => $phoneNumber_ + ); + + $this->_requestBody = http_build_query($params, '', '&'); + $this->_requestUrl = $this->getVoiceUrl() . "/mediaUpload"; + + $this->executePOST(); + } + + + //Airtime method + public function sendAirtime($recipients) + { + $params = array( + "username" => $this->_username, + "recipients" => $recipients + ); + $this->_requestUrl = $this->getAirtimeUrl("/send"); + $this->_requestBody = http_build_query($params, '', '&'); + + $this->executePOST(); + + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $responseObject = json_decode($this->_responseBody); + if(count($responseObject->responses) > 0) + return $responseObject->responses; + + throw new AfricasTalkingGatewayException($responseObject->errorMessage); + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + // Payments + public function bankPaymentCheckoutCharge($productName_, + $bankAccount_, + $currencyCode_, + $amount_, + $narration_, + $metadata_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "bankAccount" => $bankAccount_, + "currencyCode" => $currencyCode_, + "amount" => $amount_, + "narration" => $narration_, + "metadata" => $metadata_)); + $this->_requestUrl = $this->getBankPaymentCheckoutChargeUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "PendingValidation") return $response->transactionId; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function bankPaymentCheckoutValidation($transactionId_, + $otp_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "transactionId" => $transactionId_, + "otp" => $otp_)); + + $this->_requestUrl = $this->getBankPaymentCheckoutValidationUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "Success") return; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + + } + + public function bankPaymentTransfer($productName_, + $recipients_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "recipients" => $recipients_)); + $this->_requestUrl = $this->getBankPaymentTransferUrl(); + + $this->executeJsonPOST(); + + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "Success") return $response->transactionId; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + + public function cardPaymentCheckoutCharge($productName_, + $paymentCard_, + $currencyCode_, + $amount_, + $narration_, + $metadata_) { + + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "paymentCard" => $paymentCard_, + "currencyCode" => $currencyCode_, + "amount" => $amount_, + "narration" => $narration_, + "metadata" => $metadata_)); + $this->_requestUrl = $this->getCardPaymentCheckoutChargeUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "PendingValidation") return $response->transactionId; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function cardPaymentCheckoutChargeWithToken($productName_, + $checkoutToken_, + $currencyCode_, + $amount_, + $narration_, + $metadata_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "checkoutToken" => $checkoutToken_, + "currencyCode" => $currencyCode_, + "amount" => $amount_, + "narration" => $narration_, + "metadata" => $metadata_)); + $this->_requestUrl = $this->getCardPaymentCheckoutChargeUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "Success") return $response->transactionId; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function cardPaymentCheckoutValidation($transactionId_, + $otp_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "transactionId" => $transactionId_, + "otp" => $otp_)); + + $this->_requestUrl = $this->getCardPaymentCheckoutValidationUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "Success") return $response->checkoutToken; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + + } + + + public function initiateMobilePaymentCheckout($productName_, + $phoneNumber_, + $currencyCode_, + $amount_, + $metadata_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "phoneNumber" => $phoneNumber_, + "currencyCode" => $currencyCode_, + "amount" => $amount_, + "metadata" => $metadata_)); + $this->_requestUrl = $this->getMobilePaymentCheckoutUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + if ( $response->status == "PendingConfirmation") return $response->transactionId; + else throw new AfricasTalkingGatewayException($response->description); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function mobilePaymentB2CRequest($productName_, + $recipients_) { + $this->_requestBody = json_encode(array("username" => $this->_username, + "productName" => $productName_, + "recipients" => $recipients_)); + $this->_requestUrl = $this->getMobilePaymentB2CUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + $entries = $response->entries; + if (count($entries) > 0) return $entries; + else throw new AfricasTalkingGatewayException($response->errorMessage); + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + public function mobilePaymentB2BRequest($productName_, $providerData_, $currencyCode_, $amount_, $metadata_) { + if(!isset($providerData_['provider']) || strlen($providerData_['provider']) == 0) + throw new AfricasTalkingGatewayException("Missing field provider"); + + if(!isset($providerData_['destinationChannel']) || strlen($providerData_['destinationChannel']) == 0) + throw new AfricasTalkingGatewayException("Missing field destinationChannel"); + + if(!isset($providerData_['destinationAccount']) || strlen($providerData_['destinationAccount']) == 0) + throw new AfricasTalkingGatewayException("Missing field destinationAccount"); + + if(!isset($providerData_['transferType']) || strlen($providerData_['transferType']) == 0) + throw new AfricasTalkingGatewayException("Missing field transferType"); + + $params = array("username" => $this->_username, + "productName" => $productName_, + "currencyCode" => $currencyCode_, + "amount"=>$amount_, + 'provider' => $providerData_['provider'], + 'destinationChannel' => $providerData_['destinationChannel'], + 'destinationAccount' => $providerData_['destinationAccount'], + 'transferType' => $providerData_['transferType'], + 'metadata' => $metadata_); + + $this->_requestBody = json_encode($params); + $this->_requestUrl = $this->getMobilePaymentB2BUrl(); + + $this->executeJsonPOST(); + if($this->_responseInfo['http_code'] == self::HTTP_CODE_CREATED) { + $response = json_decode($this->_responseBody); + return $response; + } + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + //User info method + public function getUserData() + { + $username = $this->_username; + $this->_requestUrl = $this->getUserDataUrl('?username='.$username); + $this->executeGet(); + + if ( $this->_responseInfo['http_code'] == self::HTTP_CODE_OK ) { + $responseObject = json_decode($this->_responseBody); + return $responseObject->UserData; + } + + throw new AfricasTalkingGatewayException($this->_responseBody); + } + + private function executeGet () + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Accept: application/json', + 'apikey: ' . $this->_apiKey)); + $this->doExecute($ch); + } + + private function executePost () + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_requestBody); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Accept: application/json', + 'apikey: ' . $this->_apiKey)); + + $this->doExecute($ch); + } + + private function executeJsonPost () + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_requestBody); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', + 'Content-Length: ' . strlen($this->_requestBody), + 'apikey: ' . $this->_apiKey)); + $this->doExecute($ch); + } + + private function doExecute (&$curlHandle_) + { + try { + + $this->setCurlOpts($curlHandle_); + $responseBody = curl_exec($curlHandle_); + + if ( self::Debug ) { + echo "Full response: ". print_r($responseBody, true)."\n"; + } + + $this->_responseInfo = curl_getinfo($curlHandle_); + + $this->_responseBody = $responseBody; + curl_close($curlHandle_); + } + + catch(Exeption $e) { + curl_close($curlHandle_); + throw $e; + } + } + + private function setCurlOpts (&$curlHandle_) + { + curl_setopt($curlHandle_, CURLOPT_TIMEOUT, 60); + curl_setopt($curlHandle_, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curlHandle_, CURLOPT_URL, $this->_requestUrl); + curl_setopt($curlHandle_, CURLOPT_RETURNTRANSFER, true); + } + + private function getApiHost() { + return ($this->_environment == 'sandbox') ? 'https://api.sandbox.africastalking.com' : 'https://api.africastalking.com'; + } + + private function getPaymentHost() { + return ($this->_environment == 'sandbox') ? 'https://payments.sandbox.africastalking.com' : 'https://payments.africastalking.com'; + } + + private function getVoiceHost() { + return ($this->_environment == 'sandbox') ? 'https://voice.sandbox.africastalking.com' : 'https://voice.africastalking.com'; + } + + private function getSendSmsUrl($extension_ = "") { + return $this->getApiHost().'/version1/messaging'.$extension_; + } + + private function getVoiceUrl() { + return $this->getVoiceHost(); + } + + private function getUserDataUrl($extension_) { + return $this->getApiHost().'/version1/user'.$extension_; + } + + private function getSubscriptionUrl($extension_) { + return $this->getApiHost().'/version1/subscription'.$extension_; + } + + private function getAirtimeUrl($extension_) { + return $this->getApiHost().'/version1/airtime'.$extension_; + } + + private function getBankPaymentCheckoutChargeUrl() { + return $this->getPaymentHost().'/bank/checkout/charge'; + } + + private function getBankPaymentCheckoutValidationUrl() { + return $this->getPaymentHost().'/bank/checkout/validate'; + } + + private function getBankPaymentTransferUrl() { + return $this->getPaymentHost().'/bank/transfer'; + } + + private function getCardPaymentCheckoutChargeUrl() { + return $this->getPaymentHost().'/card/checkout/charge'; + } + + private function getCardPaymentCheckoutValidationUrl() { + return $this->getPaymentHost().'/card/checkout/validate'; + } + + private function getMobilePaymentCheckoutUrl() { + return $this->getPaymentHost().'/mobile/checkout/request'; + } + + private function getMobilePaymentB2CUrl() { + return $this->getPaymentHost().'/mobile/b2c/request'; + } + + private function getMobilePaymentB2BUrl() { + return $this->getPaymentHost().'/mobile/b2b/request'; + } +} diff --git a/code/action.php b/code/action.php new file mode 100644 index 0000000..1c4763b --- /dev/null +++ b/code/action.php @@ -0,0 +1,88 @@ +$phone, "amount"=>"KES ".$amount."") + ); + + $recipientStringFormat = json_encode($recipients); + + $message = "You have received Ksh:".$amount." worth of airtime."; + + try { + + $gateway->sendAirtime($recipientStringFormat); + + $gateway->sendMessage($phone, $message); + + return True; + + } + catch(AfricasTalkingGatewayException $e){ + + return False; + + } + + } + + function mpesa_checkout($amount,$phone,$Username,$ApiKey){ + + //Create an instance of our awesome gateway class and pass your credentials + $gateway = new AfricasTalkingGateway($Username,$ApiKey, "sandbox"); + + // Specify the name of your Africa's Talking payment product + $productName = "SwahilipotHUbCodeChallenge"; + + // The 3-Letter ISO currency code for the checkout amount + $currencyCode = "KES"; + + // Any metadata that you would like to send along with this request + // This metadata will be included when we send back the final payment notification + $metadata = array( + "agentId" => "1893", + "productId" => "Test Product" + ); + + try { + + + $transactionId = $gateway->initiateMobilePaymentCheckout($productName, + $phone, + $currencyCode, + $amount, + $metadata); + + //echo "Done sending money"; + $message = "You have approved payment of Ksh ".$amount." to ".$phone; + + $gateway->sendMessage($phone, $message); + + return True; + + } + catch(AfricasTalkingGatewayException $e){ + + return $e; + + } + + } + +?> \ No newline at end of file diff --git a/code/constants.php b/code/constants.php new file mode 100644 index 0000000..7fc1c97 --- /dev/null +++ b/code/constants.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/code/payment_status.php b/code/payment_status.php new file mode 100644 index 0000000..995521a --- /dev/null +++ b/code/payment_status.php @@ -0,0 +1,85 @@ +sendMessage($phone, $message); + + } + catch(AfricasTalkingGatewayException $e){ + + return False; + + } + + + + } else if ( $category == "MobileB2C" ) { + + $phone = $data["source"]; + $value = $data["value"]; + $account = $data["clientAccount"]; + + $message = "You have payed ksh: ".$value." to ".$account; + + try { + + $gateway->sendMessage($phone, $message); + + } + catch(AfricasTalkingGatewayException $e){ + + return False; + + } + + } else if ( $category == "MobileCheckout" ) { + + $product = $data["productName"]; + $source = $data["source"]; + $phone = $data["source"]; + $amount = $data["value"]; + + + $message = "You have Payed ksh: ".$amount." to ".$source." for buying ".$data["requestMetadata"]["productId"]; + + try { + + $gateway->sendMessage($phone, $message); + + } + catch(AfricasTalkingGatewayException $e){ + + return False; + + } + + + } else { + + //other + + } + + + + +?> \ No newline at end of file diff --git a/code/ussd.php b/code/ussd.php new file mode 100644 index 0000000..0d10825 --- /dev/null +++ b/code/ussd.php @@ -0,0 +1,131 @@ +