Vonage / vonage-php-sdk-core

Vonage REST API client for PHP. API support for SMS, Voice, Text-to-Speech, Numbers, Verify (2FA) and more.
https://developer.vonage.com/
Apache License 2.0
916 stars 180 forks source link

I am was unable to send non latin letters #8

Closed Enelar closed 7 years ago

Enelar commented 8 years ago

Looks like this client lacking support of 0xFF-... characters. Which encoding should i use to transfer anything than question mark?

tjlytle commented 8 years ago

Indeed. I'll make sure that's corrected before the 1.0 release.

tjlytle commented 8 years ago

For now, manually setting the type to unicode should work for unicode (but will update this once the interfaces is better):

$message = $client->message()->send([
    'type' => 'unicode',
    'to'   => '14845551243',
    'from' => '14045558999',
    'text' => '👍'
]);

or

$message = new \Nexmo\Message\Text('14845551243', '14045558999', 'Hey, look at this: 👍', ['type' => 'unicode']);
$client->message()->send($message);
bakura10 commented 8 years ago

Note that setting the type to unicode will restrict the length to 70 characters instead of 160 and hence, you'll be billed for more if your message is longer. There is actually a better solution outlined there: https://github.com/quinncomendant/nexmo-client/blob/master/src/Service/Message.php

We've slightly cleaned the code and here it how it looks if you have an existing "Sms" or "Message" class with a "$content" property that represents the SMS content:

public function requiresUnicodeEncoding(): bool
    {
        // Valid GSM default character-set codepoint values from http://unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT
        $gsmCodePoints = [
            0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC, 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5, 0x0394,
            0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8, 0x03A3, 0x0398, 0x039E, 0x00A0, 0x000C, 0x005E, 0x007B, 0x007D, 0x005C, 0x005B,
            0x007E, 0x005D, 0x007C, 0x20AC, 0x00C6, 0x00E6, 0x00DF, 0x00C9, 0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027, 0x0028,
            0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
            0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x00A1, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A,
            0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00C4,
            0x00D6, 0x00D1, 0x00DC, 0x00A7, 0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C,
            0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1,
            0x00FC, 0x00E0
        ];

        // Split $text into an array in a way that respects multibyte characters.
        $textChars = preg_split('//u', $this->content, null, PREG_SPLIT_NO_EMPTY);

        // Array of codepoint values for characters in $text.
        $textCodePoints = array_map(function ($char) {
            $k = mb_convert_encoding($char, 'UCS-2LE', 'UTF-8');
            $k1 = ord(substr($k, 0, 1));
            $k2 = ord(substr($k, 1, 1));
            return $k2 * 256 + $k1;
        }, $textChars);

        // Filter the array to contain only codepoints from $text that are not in the set of valid GSM codepoints.
        $nonGsmCodePoints = array_diff($textCodePoints, $gsmCodePoints);

        // The text contains unicode if the result is not empty.
        return !empty($nonGsmCodePoints);
    }

In your code that sends the SMS, you can now use this method to check if the message requires unicode or not. This way you make the better use of your money :).

tjlytle commented 8 years ago

In the code, you'll see there's an untested Unicode message class (along with others for Binary, Wap, etc). I just haven't migrated them over yet.

@bakura10 I was thinking of implementing some kind of auto detect, but feel like that (picking unicode) is really something for the user.

Will give it some more thought.

bakura10 commented 8 years ago

Definitely, but on my case as I don't control the messages (they are written by the user), I didn't want that if the user entered ネクスモはすごいだ! it would be sent as "???????" ;).

You could maybe add an option to the class that sends the message, like "$bestEncodingFit" that, if set to true, would let the SDK to choose the most appropriate for the user.

Enelar commented 8 years ago

@tjlytle related to this topic. What i should do if i sometimes receiving question marks or пїЅ through API smsInbound?

Real world examples:

????????????5?????????????????????пїЅ????????????????????пїЅ???????????inguna informaciпїЅn para 

????

Yo no pedпїЅ nada

Last one is most likely 'yo no pedido nada'

tjlytle commented 8 years ago

@Enelar Do you have any steps to duplicate that, or does it seem to happen sometimes (perhaps based on the carrier)?

Enelar commented 8 years ago

@tjlytle i will try to send not latin message to our number, but if it not enough to reproduce, i am afraid i cant help with that.

mheap commented 7 years ago

An initial implementation of this was released in v1.0.0

Asxer commented 7 years ago

@mheap Hello! I'm trying to send emoji in sms. I upgraded this package and nexmo/laravel package to 1.0.0 version. I try to call example above

$nexmo = app(\Nexmo\Client::class);

$nexmo->message()->send([
    'type' => 'unicode',
    'to'   => $phone,
    'from' => config('nexmo.from'),
    'text' => '👍'
]);

As result i got many ?? symbols instead of emoji and non-latin symbols. Could you please explain how can i fix it?

php version 5.6.30-0+deb8u1

mheap commented 7 years ago

Hi @Asxer,

This issue has been marked as closed, so I've moved your query to a new issue (#79). Let's work on the issue there

Thanks, Michael

akasham67 commented 5 years ago

Hi,

I got same issue with Laravel application. Here is my code block:

 $message = 'this test message 😀こんにちは世界';
 $nexmo = new \Nexmo\Client(new Basic('api_key', 'api_secret'));
 $sms_data = [
       'to' => $phone,
       'from' => $sender_id,
       'text' => $message,
       'type' => 'unicode'
     ];
$response = $nexmo->message()->send($sms_data);

Everything work perfectly but emoji receive as ??? (what sign)

PHP Version: 7.2 Laravel Framework: 5.4 Nexmo-php: 1.0.0