0

我正在开发一个应该有一些支付选项的小型网上商店。我的平台是 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-friendly hosting”,正如在一个关于在应用引擎上实际运行 satchmo 的类似问题中所建议的那样?

4

1 回答 1

3

做了一些研究,看起来很多人都尝试过这个并放弃了。在应用引擎上运行 satchmo 有几个问题 - 大多数与模型和依赖项有关,但也存在 PCI 合规性问题。

我将首先解决 PCI 方面的问题 - 为了能够存储信用卡数据而不必担心您的商家帐户提供商会拔掉您的帐户,您需要遵守 PCI DSS。如果您打算与信用卡数据进行交互,这是一份由律师编写的文件(哈!),用于设定安全标准。这主要是良好的最佳实践,例如从不存储 CVV2(卡背面的 3 位代码)等等。然而,一个重要方面与所用存储的安全性有关。谷歌没有宣传这一点,但我相当有信心 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-自适应支付和谷歌应用引擎构建在线市场 python

此外,此代码可能会根据您的需要进行调整。他们正在使用谷歌结帐: http ://code.google.com/p/chippysshop/

最后是 Stripe,它可以处理各种信用卡交易,并且不需要商家帐户:https ://stripe.com/

祝你好运!

于 2011-12-26T01:58:22.043 回答