Thursday, March 10, 2016

[Amazon/SNS] AWS SNS publish SMS PHP 5.6 Implementation

Recently, I decided to add a verification code thru SMS to validate the user login. After I the feasibility of how my project integrate this feature, I decided to give AWS SNS a try since I already got a few services from them.

Here I wanna share my experience of how to set this up and hope it helps someone.

My server environment for this setup: 
Windows 7 IIS 7.5, PHP 5.6.19, AWS SDK PHP v3


First, download and install AWS SDK PHP

my SDK PHP version is v3. and the minimum PHP version is 5.5

The first problem that came to me was when I tried to config OPCache following the Optimal Settings , I got Html error 500 when run phpinfo(). It took me some times to figure out the event log and it shown me Zend Opcache:
"Unable to reattach to base address
Attempt to access invalid address." 
For more information, you can see here.

Anyway, I finally followed the most easy fix, just set permission to 'everyone' on the temp folder, thanks to fedevegili the one who suggested.

Ok, before you can run the API the SDK provided successfully, you need to create an AWS account  of course, as well as getting the Access key ID and Secret for the authentication putting in your script. 

I created an user solely for all functions of SNS via IAM. There are several ways to configure your Credential File, I choose a file location I preferred instead of the default anyway, and setup like follows:

<?php
//these two lines placed on top of the script
use Aws\Credentials\CredentialProvider;
use Aws\Sns\SnsClient;

$provider = CredentialProvider::ini('default', '/aws/credentials.ini');
$sns = SnsClient::factory(array(
            'version' => 'latest',
            'region'  => 'us-east-1',
            'credentials' => CredentialProvider::memoize($provider)
));
?>

credentials.ini
[default]
aws_access_key_id = <YOUR AWS ACCESS KEY ID>
aws_secret_access_key = <YOUR AWS SECRET ACCESS KEY>

Next, I followed here to create my first "Topic" in SNS.
  1. Make sure you set the region to "us-east-1"; otherwise, the option "SMS" won't be show up in the drop-down list for you select when you create "Subscription" later.
  2. Display Name must be given, and this Display Name will be show at the beginning of the SMS message followed by a ">" sign then your actual message.
After that, I created a subscription with protocol "SMS" and a mobile phone number as the Endpoint. Then you need to send a confirmation request to the Subscription(the User), and the user need to reply 'YES' for receiving further SMS from you. 

As of today, 3/10/16, be aware that the API "publish" will only work as sending all subscriptions under a Topic. Although I see someone is able to send to specific Endpoint, they all have "Applications" defined in the middle for their specific Endpoint works; however, I don't have one (Application). 

This is not a big problem though, I made one topic for one subscription only for one Endpoint (mobile number).  The thing is you may need to know which topic you're going to send for the specific Endpoint. 

Since the format of TopicArn is like 
arn:aws:sns:<Region>:<Subscriber/Topic Owner>:<TopicName>
I can use the TopicName to distinguish who I'm going to send, and like this

$region="us-east-1";
$subscriber="1234567890";
$topicName="USER001";
$TargetArn="arn:aws:sns:".$region.$subscriber.":".$topicName;
$Message="Hello World!";
$sns->publish(array('TargetArn'=>$TargetArn,'Message' => $Message)); 

Hope you Enjoy!

Monday, October 26, 2015

php 5.4/5.6 MS SQL 2005/2008 - sqlstate im002 "microsoft odbc driver manager data source name not found"

Recently, I setup a new IIS on a windows 10 to connect a MS SQL server with PHP;  I got this Error Message, "sqlstate:  im002,  message: microsoft odbc driver manager data source name not found", when trying to connect to the server.

I tried to google the answer, but no one could solve my problem, most of the answers directed to the incorrectly version of ODBC driver. But it was not my case.

Eventually, I compared the new server configurations to my working one, and found that

"SQL Server Native Client 11.0" is installed.

so, I wrote this down and hope this helps someone.

p.s. if you've trouble to locate the download link of "SQL Server native Client"

take a look here: http://www.sqlservercentral.com/Forums/Topic1458276-2799-1.aspx


Updated on 20161217: Recently, I encountered the same problem with the environment like PHP 5.4 with SQL Server 2005 (SP4) and tried to move it to PHP 5.6.

I found no solution for this issue even updated the SQL Server native client from 11 to 12. I only can choose either to stay "PHP 5.4 with SQL Server 2005 (SP4)" or move to "SQL Server 2008 (and after)" if I want PHP 5.6.

2nd, since I've added a new feature to the current system that will work with AWS SMS, and PHP 5.5 is the minimum requirement for the AWS SDK.

Thus, in this case, I have to move the DB from 2005 to 2008 R2 and make it works with PHP 5.6.





Sunday, September 21, 2014

[Android] A simple trick to watch unsupport video format directly from Sandisk Wireless Flash

I just got a Sandisk Wireless Flash and mainly for storing up videos that I can watch on my mobile device (mine one is Samsung S3 and Tab 3) anytime.

However, when I tried to watch rmvb and mkv, a message pop up and it said  'your Android device cannot view this type of file.'

Even I did try the Realplayer Cloud that the Sandisk recommends this approach, I cannot see my Sandisk device under the Realplayer Cloud with following steps:

http://kb.sandisk.com/app/answers/detail/a_id/10539/~/playing-videos-that-are-not-natively-supported-by-your-mobile-device

When I almost gave up, an idea came into my mind. How about if I rename the file type into avi that Android native support?

Then, it is just that simple. Rename the file type!

example 1:
rename video1.rmvb  to video.avi

example 2:
rename video2.mkv to video.avi

(mp4 also works)

Yes, that's it. Now, we can click on the video file you renamed and Android now allows you to pick what video player in your device to play it.

Lastly, of course, you need to install a video player, that is able to play the particular video format, into your device beforehand.

I am using MX player if you want know what works for me.


Thursday, February 6, 2014

Angularjs - number only input directives

app.js:
app.directive('numberOnly', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            ngModel: '='
        },
        link: function (scope) {          
            scope.$watch('ngModel', function(newValue,oldValue) {        
                var arr = String(newValue).split("");
                if (arr.length === 0) return;
                if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.' )) return;
                if (arr.length === 2 && newValue === '-.') return;
                if (isNaN(newValue)) {
                    scope.ngModel = oldValue;
                }
            });
        }
    };
});

app.controller('MainCtrl', function($scope) {
  $scope.name = 0;
});

html:
<body ng-controller="MainCtrl">
    <input type="text" ng-model="name" number-only/>
</body>


That's it and simple.
demo here

Wednesday, February 5, 2014

Angularjs ng-grid : rowItem.rowIndex not map to the index of data array after sorting. (with solution)

I found that the rowIndex will no longer map to the index of the data array if sorting is applied.
Lastly, I found a way to locate the index of data array even after sorting is applied by using rowMap and the syntax like this:
$scope.gridOptions.ngGrid.rowMap.indexOf(rowItem.rowIndex);

instead of just using rowItem.rowIndex.


however, this is not officially documented. 
So, beware that there is any changes in the future updates/patches of the ng-grid. 
updated on 05 Feb 2014

With further studies, I found that selectedItems may serves the same purpose only when the multiSelect equals to false. So, it won't work exactly the same if you require the grid with multiSelect:true.

Thursday, April 25, 2013

windows 7 setup was unable to create a new system partition or locate an existing system partition.

I was installing windows 7 on a machine that already was installed an Operation system on C: drive.

And I planned to install the windows 7 on a new raw hard drive with Basic type partition.

When it asked for which disk for this installation, I got this error "unable to create a new system partition or locate an existing system partition" when I picked the new hard drive.

After I read a few threads on the internet, I found that "Disable C: drive boot up" in Bios, then it allowed me this installation again.

Thursday, March 21, 2013

Android - CookieSyncManager to prevent Webview lost session after Pause Resume

By adding CookieSyncManager onCreate of Activity and also on corresponding events like onPause and onResume, taking care my session ID for the PHP server when the Activity/WebView reloads.

public class MainActivity extends Activity {
    @Override
     protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);

           CookieSyncManager.createInstance(this); 
           CookieSyncManager.getInstance().startSync();

           WebView myWebView = ((WebView)findViewById(R.id.webview));
           myWebView.setWebViewClient(new WebViewClient());
    }
   @Override
    protected void onResume() {
           super.onResume();
           CookieSyncManager.getInstance().stopSync();
    }
    @Override
     protected void onPause() {
           super.onPause();
           CookieSyncManager.getInstance().sync();
    }
}