0

私はいくつかの支払いオプションがあるはずの小さなウェブショップを開発しています。私のプラットフォームはGoogleAppEngineとPython2.7です。django / pythonであるsatchmoというプロジェクトがあり、そのコードを使用できるかどうか疑問に思います。支払いのモデルのいくつかのオープンソースは次のとおりです

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プロジェクトは、Webショップを実装するときに直面する問題の多くをすでに解決していると思いますか?それとも、アプリエンジンで実際にsatchmoを実行することについての同様の質問で提案されたように、もっと「djangoに適したホスティング」を取得する必要がありますか?

4

1 に答える 1

3

いくつかの調査を行うと、多くの人がこれを試し、あきらめたようです。アプリエンジンでsatchmoを実行することにはいくつかの問題があります。ほとんどはモデルと依存関係に関連していますが、PCIコンプライアンスの問題もあります。

最初にPCIの側面について説明します-マーチャントアカウントプロバイダーがアカウントのプラグを抜くことを恐れずにクレジットカードデータを保存できるようにするには、PCIDSSに準拠する必要があります。これは、クレジットカードのデータを操作する場合に、セキュリティの基準を設定するために弁護士(ha!)によって作成されたドキュメントです。これは、CVV2(カードの裏面に3桁のコード)を保存しないなど、ほとんどの場合、優れたベストプラクティスです。ただし、1つの大きな側面は、使用されるストレージのセキュリティに関係しています。Googleはこれを宣伝していませんが、AppEngineとその独自のDBはPCIに準拠していないと確信しています。これは、上に構築したものがPCIに準拠することは決してないことを意味します。

今、技術的な側面。私が読んだことから、これを機能させるための最善の策はdjango_nonrelです。外部キーに依存しないように一部のモデルを変更する必要があります。reportlabなど、他にもいくつかの依存関係があります。これについて話している投稿は次のとおりです:http://groups.google.com/group/satchmo-developers/browse_thread/thread/f14053df13232615

最後になりましたが、stackoverflowに関する以前の議論は次のとおりです。GoogleAppEngineでSatchmoを機能させる方法

一般的なコンセンサスは、satchmoはGAEには適していないということです。すぐに使えるソリューションはないようですが、Paypalをご覧になることをお勧めします。ここにそれらのチュートリアルがあります:https ://www.x.com/devzone/articles/using-paypals- Adaptal-payments-and-google-app-engine-build-online-market-python

また、このコードは必要なものに適合している可能性があります。彼らはグーグルチェックアウトを使用しています: http ://code.google.com/p/chippysshop/

最後に、あらゆる種類のクレジットカード取引を処理し、マーチャントアカウントを必要としないStripeがあります:https ://stripe.com/

幸運を!

于 2011-12-26T01:58:22.043 に答える