Обработка платежей для интернет-магазина с питоном 2.7 в GAE? - PullRequest
0 голосов
/ 25 декабря 2011

Я разрабатываю небольшой интернет-магазин, в котором должно быть несколько вариантов оплаты.Моя платформа - Google App Engine и Python 2.7.Есть проект под названием satchmo, который называется django / python, и мне интересно, смогу ли я использовать его код? Здесь является открытым исходным кодом для некоторых моделей платежей:

class PaymentOption(models.Model):
    """
    If there are multiple options - CC, Cash, COD, etc this class allows
    configuration.
    """
    description = models.CharField(_("Description"), max_length=20)
    active = models.BooleanField(_("Active"), 
        help_text=_("Should this be displayed as an option for the user?"))
    optionName = models.CharField(_("Option Name"), max_length=20, choices=iterchoices_db(payment.config.labelled_gateway_choices),
        unique=True, 
        help_text=_("The class name as defined in payment.py"))
    sortOrder = models.IntegerField(_("Sort Order"))

    class Meta:
        verbose_name = _("Payment Option")
        verbose_name_plural = _("Payment Options")

class CreditCardDetail(models.Model):
    """
    Stores an encrypted CC number, its information, and its
    displayable number.
    """
    orderpayment = models.ForeignKey('shop.OrderPayment', unique=True, 
        related_name="creditcards")
    credit_type = models.CharField(_("Credit Card Type"), max_length=16, choices=iterchoices_db(payment.config.credit_choices))
    display_cc = models.CharField(_("CC Number (Last 4 digits)"),
        max_length=4, )
    encrypted_cc = models.CharField(_("Encrypted Credit Card"),
        max_length=40, blank=True, null=True, editable=False)
    expire_month = models.IntegerField(_("Expiration Month"))
    expire_year = models.IntegerField(_("Expiration Year"))
    card_holder = models.CharField(_("card_holder Name"), max_length=60, blank=True)
    start_month = models.IntegerField(_("Start Month"), blank=True, null=True)
    start_year = models.IntegerField(_("Start Year"), blank=True, null=True)
    issue_num = models.CharField(blank=True, null=True, max_length=2)

    def storeCC(self, ccnum):
        """Take as input a valid cc, encrypt it and store the last 4 digits in a visible form"""
        self.display_cc = ccnum[-4:]
        encrypted_cc = _encrypt_code(ccnum)
        if config_value('PAYMENT', 'STORE_CREDIT_NUMBERS'):
            self.encrypted_cc = encrypted_cc
        else:
            standin = "%s%i%i%i" % (self.display_cc, self.expire_month, self.expire_year, self.orderpayment.id)
            self.encrypted_cc = _encrypt_code(standin)
            key = _encrypt_code(standin + '-card')
            keyedcache.cache_set(key, skiplog=True, length=60*60, value=encrypted_cc)

    def setCCV(self, ccv):
        """Put the CCV in the cache, don't save it for security/legal reasons."""
        if not self.encrypted_cc:
            raise ValueError('CreditCardDetail expecting a credit card number to be stored before storing CCV')

        keyedcache.cache_set(self.encrypted_cc, skiplog=True, length=60*60, value=ccv)

    def getCCV(self):
        try:
            ccv = keyedcache.cache_get(self.encrypted_cc)
        except keyedcache.NotCachedError:
            ccv = ""

        return ccv

    ccv = property(fget=getCCV, fset=setCCV)

    def _decryptCC(self):
        ccnum = _decrypt_code(self.encrypted_cc)
        if not config_value('PAYMENT', 'STORE_CREDIT_NUMBERS'):
            try:
                key = _encrypt_code(ccnum + '-card')
                encrypted_ccnum = keyedcache.cache_get(key)
                ccnum = _decrypt_code(encrypted_ccnum)
            except keyedcache.NotCachedError:
                ccnum = ""
        return ccnum

    decryptedCC = property(_decryptCC) 

    def _expireDate(self):
        return(str(self.expire_month) + "/" + str(self.expire_year))
    expirationDate = property(_expireDate)

    class Meta:
        verbose_name = _("Credit Card")
        verbose_name_plural = _("Credit Cards")

def _decrypt_code(code):
    """Decrypt code encrypted by _encrypt_code"""
    # In some blowfish implementations, > 56 char keys can cause problems
    secret_key = settings.SECRET_KEY[:56]
    encryption_object = Blowfish.new(secret_key)
    # strip padding from decrypted credit card number
    return encryption_object.decrypt(base64.b64decode(code)).rstrip('X')

def _encrypt_code(code):
    """Quick encrypter for CC codes or code fragments"""
    # In some blowfish implementations, > 56 char keys can cause problems
    secret_key = settings.SECRET_KEY[:56]
    encryption_object = Blowfish.new(secret_key)
    # block cipher length must be a multiple of 8
    padding = ''
    if (len(code) % 8) <> 0:
        padding = 'X' * (8 - (len(code) % 8))
    return base64.b64encode(encryption_object.encrypt(code + padding))

Код выглядит переносимым на движок приложения, и, если я захочу, могу или даже должен портировать этот код, думая, чтопроект satchmo уже решил многие проблемы, с которыми я столкнусь при внедрении своего интернет-магазина?Или я должен просто получить более «дружественный к django хостинг», как было предложено в аналогичном вопросе о фактическом запуске satchmo на движке приложения?

1 Ответ

3 голосов
/ 26 декабря 2011

Проводя некоторые исследования, похоже, что многие люди пытались это сделать и сдались.Есть несколько проблем с запуском satchmo на движке приложения - большинство из них связаны с моделями и зависимостями, но есть также вопрос соответствия PCI.

Сначала я рассмотрю аспект PCI - чтобы иметь возможностьХраните данные кредитной карты, не опасаясь, что ваш поставщик торговых счетов отключит вашу учетную запись, вам необходимо соблюдать PCI DSS.Это документ, написанный юристами (ха!), Чтобы установить стандарты безопасности, если вы собираетесь взаимодействовать с данными кредитной карты.В основном это хорошие передовые практики, такие как никогда не хранить CVV2 (трехзначный код на обратной стороне карты) и так далее.Однако один большой аспект связан с безопасностью используемого хранилища.Google не рекламирует это, но я вполне уверен, что App Engine и их собственная БД не соответствуют PCI.Это означает, что все, что вы строите на вершине, никогда не будет совместимым с PCI.

Теперь технический аспект.Из того, что я прочитал, ваш лучший выбор для получения этой работы - django_nonrel .Вам придется изменить некоторые модели, чтобы они не зависели от внешних ключей.Есть также некоторые другие вызываемые зависимости, такие как reportlab.Вот пост, в котором говорится об этом: http://groups.google.com/group/satchmo-developers/browse_thread/thread/f14053df13232615

И последнее, но не менее важное, вот старое обсуждение stackoverflow: Как заставить Satchmo работать в Google App Engine

Общее мнение заключается в том, что satchmo не очень подходит для GAE.Кажется, что нет хороших готовых решений, но я бы посоветовал вам взглянуть на Paypal, вот учебник из них: https://www.x.com/devzone/articles/using-paypals-adaptive-payments-and-google-app-engine-build-online-market-python

Кроме того, этот код может быть адаптирован для того, чтотебе нужно.Они используют Google Checkout: http://code.google.com/p/chippysshop/

Наконец, есть Stripe, который обрабатывает все виды операций с кредитными картами и не требует торгового счета: https://stripe.com/

Удачи!

...