add orange contact everyone SMS backend (#9163)
This commit is contained in:
parent
2fceba9aa4
commit
fae0e39070
|
@ -5,6 +5,7 @@ recursive-include passerelle/apps/*/static *
|
|||
# locales
|
||||
recursive-include passerelle/locale *.po *.mo
|
||||
|
||||
include passerelle/apps/orange/orange.pem
|
||||
include LICENSE
|
||||
include MANIFEST.in
|
||||
include VERSION
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
from django.utils.text import slugify
|
||||
from django import forms
|
||||
|
||||
from .models import OrangeSMSGateway
|
||||
|
||||
class OrangeSMSGatewayForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = OrangeSMSGateway
|
||||
exclude = ('slug', 'users')
|
||||
|
||||
def save(self, commit=True):
|
||||
if not self.instance.slug:
|
||||
self.instance.slug = slugify(self.instance.title)
|
||||
return super(OrangeSMSGatewayForm, self).save(commit=commit)
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import passerelle.sms
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0002_auto_20151009_0326'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='OrangeSMSGateway',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('title', models.CharField(max_length=50)),
|
||||
('slug', models.SlugField()),
|
||||
('description', models.TextField()),
|
||||
('keystore', models.FileField(help_text='Certificate and private key in PEM format', upload_to=b'orange', null=True, verbose_name='Keystore', blank=True)),
|
||||
('users', models.ManyToManyField(to='base.ApiUser', blank=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'sms_orange',
|
||||
'verbose_name': 'Orange',
|
||||
},
|
||||
bases=(models.Model, passerelle.sms.SMSGatewayMixin),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,60 @@
|
|||
import re
|
||||
import urllib
|
||||
import urllib2
|
||||
import logging
|
||||
import json
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db import models
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
from passerelle.sms import SMSGatewayMixin
|
||||
|
||||
from . import soap
|
||||
|
||||
class OrangeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class OrangeSMSGateway(BaseResource, SMSGatewayMixin):
|
||||
keystore = models.FileField(upload_to='orange',
|
||||
blank=True, null=True,
|
||||
verbose_name=_('Keystore'),
|
||||
help_text=_('Certificate and private key in PEM format'))
|
||||
default_country_code = '33'
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Orange'
|
||||
db_table = 'sms_orange'
|
||||
|
||||
@classmethod
|
||||
def get_verbose_name(cls):
|
||||
return cls._meta.verbose_name
|
||||
|
||||
@classmethod
|
||||
def get_icon_class(cls):
|
||||
return 'phone'
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('orange-view', kwargs={'slug': self.slug})
|
||||
|
||||
@classmethod
|
||||
def get_add_url(cls):
|
||||
return reverse('orange-add')
|
||||
|
||||
def get_edit_url(self):
|
||||
return reverse('orange-edit', kwargs={'slug': self.slug})
|
||||
|
||||
def get_delete_url(self):
|
||||
return reverse('orange-delete', kwargs={'slug': self.slug})
|
||||
|
||||
def send(self, text, sender, destinations):
|
||||
logger = logging.getLogger('passerelle.apps.orange')
|
||||
"""Send a SMS using the Orange provider"""
|
||||
# unfortunately it lacks a batch API...
|
||||
destinations = self.clean_numbers(destinations, self.default_country_code)
|
||||
|
||||
logger.info(u'sending sms with sender %s to %s', sender, u', '.join(destinations))
|
||||
logger.debug(u'sms content: %s', text)
|
||||
soap.ContactEveryoneSoap(instance=self).send_advanced_message(destinations, sender, text)
|
|
@ -0,0 +1,15 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICWzCCAcQCAQAwDQYJKoZIhvcNAQEEBQAwdjELMAkGA1UEBhMCRlIxDzANBgNV
|
||||
BAgTBkZyYW5jZTENMAsGA1UEBxMEQ2FlbjEXMBUGA1UEChMORnJhbmNlIFRlbGVj
|
||||
b20xDDAKBgNVBAsTA0RQUzEMMAoGA1UEAxMDRERQMRIwEAYJKoZIhvcNAQkBFgNE
|
||||
SU0wHhcNMDYxMTA4MjAyNDUxWhcNMTYxMTA1MjAyNDUxWjB2MQswCQYDVQQGEwJG
|
||||
UjEPMA0GA1UECBMGRnJhbmNlMQ0wCwYDVQQHEwRDYWVuMRcwFQYDVQQKEw5GcmFu
|
||||
Y2UgVGVsZWNvbTEMMAoGA1UECxMDRFBTMQwwCgYDVQQDEwNERFAxEjAQBgkqhkiG
|
||||
9w0BCQEWA0RJTTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxp5nnfYr4ZsV
|
||||
QgIzYkz42Urc+0z49cm8JL5DQAcceIUpWYnCOSjDCEivvkYlBGEaSQhx6goLgpAk
|
||||
6264BhFIa9tFJBz0VCbZ5erGANNFpi1zK9nglfGMkfgQmPXFcVF+hi9ztff+WHGR
|
||||
SknuxzXAICG0/PfPy/LcpVC9E35IkG8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQAk
|
||||
plMn6da0Yu2YZ7dSP9UBrWygN3iD93Krk5H9KcJCFKXRcZsKw/871J+fFxOFxe5u
|
||||
l/wraMBF+oo9aMBIsrHwzPkPr6/T3+cYScJAcoP0vRqGjbhio1BvoSvH4lsfmJsF
|
||||
L9cgc58xgDNwztKHqggDtiFCWVEBpYk2jbMnoy7/xg==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,76 @@
|
|||
import logging
|
||||
import datetime
|
||||
import os.path
|
||||
|
||||
|
||||
from passerelle.soap import Soap
|
||||
from passerelle.xml_builder import XmlBuilder
|
||||
|
||||
|
||||
class ContactEveryoneSoap(Soap):
|
||||
WSDL_URL = ('https://www.api-contact-everyone.fr.orange-business.com/'
|
||||
'ContactEveryone/services/MultiDiffusionWS?wsdl')
|
||||
ORANGE_CERTIFICATE = os.path.join(os.path.dirname(__file__), 'orange.pem')
|
||||
|
||||
url = WSDL_URL
|
||||
|
||||
class ProfileListBuilder(XmlBuilder):
|
||||
schema = (
|
||||
'PROFILE_LIST',
|
||||
('?loop', 'recipients',
|
||||
('PROFILE',
|
||||
('DEST_NAME', 'name_{to}'),
|
||||
('DEST_FORENAME', 'forename_{to}'),
|
||||
('DEST_ID', 'ID_{to}'),
|
||||
('TERMINAL_GROUP',
|
||||
('TERMINAL',
|
||||
('TERMINAL_NAME', 'mobile1'),
|
||||
('TERMINAL_ADDR', '{to}'),
|
||||
('MEDIA_TYPE_GROUP',
|
||||
('MEDIA_TYPE', 'sms')))))))
|
||||
encoding = 'latin1'
|
||||
|
||||
@property
|
||||
def verify(self):
|
||||
# Do not break if certificate is not updated
|
||||
if datetime.datetime.now() < datetime.datetime(2016, 11, 5):
|
||||
return self.ORANGE_CERTIFICATE
|
||||
else:
|
||||
return False
|
||||
|
||||
def send_message(self, recipients, content):
|
||||
client = self.get_client()
|
||||
message = client.factory.create('WSMessage')
|
||||
message.fullContenu = True
|
||||
message.content = content
|
||||
message.subject = content
|
||||
message.resumeContent = content
|
||||
message.strategy = 'sms'
|
||||
send_profiles = self.ProfileListBuilder().string(
|
||||
context={'recipients': [{'to': to} for to in recipients]})
|
||||
message.sendProfiles = send_profiles
|
||||
# XXX: handle webfault and other problems
|
||||
try:
|
||||
client.service.sendMessage(message)
|
||||
except Exception, e:
|
||||
logging.getLogger(__name__).exception('failed to send sms')
|
||||
raise
|
||||
|
||||
def send_advanced_message(self, recipients, sender, content):
|
||||
client = self.get_client()
|
||||
message = client.factory.create('WSAdvancedMessage')
|
||||
message.fullContenu = True
|
||||
message.content = content
|
||||
message.subject = content
|
||||
message.resumeContent = content
|
||||
message.strategy = 'sms'
|
||||
message.smsReplyTo = sender
|
||||
send_profiles = self.ProfileListBuilder().string(
|
||||
context={'recipients': [{'to': to} for to in recipients]})
|
||||
message.sendProfiles = send_profiles
|
||||
# XXX: handle webfault and other problems
|
||||
try:
|
||||
return client.service.sendAdvancedMessage(message)
|
||||
except Exception, e:
|
||||
logging.getLogger(__name__).exception('failed to send sms')
|
||||
raise
|
|
@ -0,0 +1,13 @@
|
|||
from django.conf.urls import patterns, url
|
||||
from views import *
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^(?P<slug>[\w,-]+)/$', OrangeDetailView.as_view(), name='orange-view'),
|
||||
url(r'^(?P<slug>[\w,-]+)/send$', OrangeSendView.as_view(), name='orange-send'),
|
||||
)
|
||||
|
||||
management_urlpatterns = patterns('',
|
||||
url(r'^add$', OrangeCreateView.as_view(), name='orange-add'),
|
||||
url(r'^(?P<slug>[\w,-]+)/edit$', OrangeUpdateView.as_view(), name='orange-edit'),
|
||||
url(r'^(?P<slug>[\w,-]+)/delete$', OrangeDeleteView.as_view(), name='orange-delete'),
|
||||
)
|
|
@ -0,0 +1,37 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
|
||||
from passerelle.base.views import ResourceView
|
||||
from passerelle.sms.views import SendView
|
||||
|
||||
from .models import OrangeSMSGateway
|
||||
from .forms import OrangeSMSGatewayForm
|
||||
|
||||
|
||||
class OrangeDetailView(ResourceView):
|
||||
model = OrangeSMSGateway
|
||||
template_name = 'passerelle/manage/messages_service_view.html'
|
||||
|
||||
|
||||
class OrangeCreateView(CreateView):
|
||||
model = OrangeSMSGateway
|
||||
template_name = 'passerelle/manage/service_form.html'
|
||||
form_class = OrangeSMSGatewayForm
|
||||
|
||||
|
||||
class OrangeUpdateView(UpdateView):
|
||||
model = OrangeSMSGateway
|
||||
template_name = 'passerelle/manage/service_form.html'
|
||||
form_class = OrangeSMSGatewayForm
|
||||
|
||||
|
||||
class OrangeDeleteView(DeleteView):
|
||||
model = OrangeSMSGateway
|
||||
template_name = 'passerelle/manage/service_confirm_delete.html'
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('manage-home')
|
||||
|
||||
|
||||
class OrangeSendView(SendView):
|
||||
model = OrangeSMSGateway
|
|
@ -111,6 +111,7 @@ INSTALLED_APPS = (
|
|||
'bdp',
|
||||
'base_adresse',
|
||||
'csvdatasource',
|
||||
'orange',
|
||||
# backoffice templates and static
|
||||
'gadjo',
|
||||
)
|
||||
|
@ -123,6 +124,7 @@ PASSERELLE_APP_CHOOSIT_ENABLED = True
|
|||
PASSERELLE_APP_OXYD_ENABLED = True
|
||||
PASSERELLE_APP_OVH_ENABLED = True
|
||||
PASSERELLE_APP_MOBYT_ENABLED = True
|
||||
PASSERELLE_APP_ORANGE_ENABLED = True
|
||||
|
||||
PASSERELLE_APP_BDP_ENABLED = False
|
||||
PASSERELLE_APP_GDC_ENABLED = False
|
||||
|
|
|
@ -22,6 +22,7 @@ import pastell.urls
|
|||
import concerto.urls
|
||||
import bdp.urls
|
||||
import base_adresse.urls
|
||||
import orange.urls
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
|
@ -131,6 +132,15 @@ urlpatterns += required(
|
|||
)
|
||||
)
|
||||
|
||||
urlpatterns += required(
|
||||
app_enabled('orange'),
|
||||
patterns('',
|
||||
url(r'^orange/', include(orange.urls.urlpatterns)),
|
||||
url(r'^manage/orange/',
|
||||
decorated_includes(login_required, include(orange.urls.management_urlpatterns))),
|
||||
)
|
||||
)
|
||||
|
||||
# add patterns from apps
|
||||
urlpatterns = register_apps_urls(urlpatterns)
|
||||
|
||||
|
|
Loading…
Reference in New Issue