python實現支付功能
#支付寶介面
import OpenSSL import json import time import urllib import base64 from django.conf import settings def build_sign(param_map, sign_type="RSA"): ''' Doc: https://doc.open.alipay.com/doc2/detail.htm?treeId=200&articleId=105351&docType=1 ''' # 將篩選的引數按照第一個字元的鍵值ASCII碼遞增排序(字母升序排序),如果遇到相同字元則按照第二個字元的鍵值ASCII碼遞增排序,以此類推。 sort_param = sorted([(key, unicode(value, settings.ALIPAY_CHARSET).encode(settings.ALIPAY_CHARSET)) for key, value in param_map.iteritems()], key=lambda x: x[0]) # 將排序後的引數與其對應值,組合成“引數=引數值”的格式,並且把這些引數用&字元連線起來,此時生成的字串為待簽名字串。SDK中已封裝簽名方法,開發者可直接呼叫,詳見SDK說明。 # 如自己開發,則需將待簽名字串和私鑰放入SHA1 RSA演算法中得出簽名(sign)的值。 content = '&'.join(['='.join(x) for x in sort_param]) return base64.encodestring(OpenSSL.crypto.sign(settings.ALIPAY_APP_PRIVATE_KEY_OBJ, content, 'sha1')) def build_params(out_trade_no, subject, body, total_amount): ''' Doc:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.MVkRGo&treeId=193&articleId=105465&docType=1 將引數按照支付寶規定組織並簽名之後,返回 ''' params = {} # 獲取配置檔案 params['app_id'] = settings.ALIPAY_APPID params['method'] = settings.ALIPAY_METHOD params['format'] = settings.ALIPAY_FORMAT params['charset'] = settings.ALIPAY_CHARSET params['sign_type'] = settings.ALIPAY_SIGN_TYPE params['sign_type'] = settings.ALIPAY_SIGN_TYPE params['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S') params['version'] = settings.ALIPAY_VERSION params['notify_url'] = settings.ALIPAY_NOTIFY_URL # 業務引數 params['biz_content'] = {} params['biz_content']['body'] = body # 訂單描述、訂單詳細、訂單備註,顯示在支付寶收銀臺裡的“商品描述”裡 params['biz_content']['subject'] = subject # 商品的標題/交易標題/訂單標題/訂單關鍵字等。 params['biz_content']['out_trade_no'] = out_trade_no # 商戶網站唯一訂單號 params['biz_content']['total_amount'] = '%.2f' % (float(total_amount) / 100) # 訂單總金額,單位為元,精確到小數點後兩位,取值範圍[0.01,100000000] params['biz_content']['product_code'] = settings.ALIPAY_APP_PRODUCT_CODE params['biz_content'] = json.dumps(params['biz_content'], separators=(',', ':')) params['sign'] = build_sign(params) return urllib.urlencode(params) def check_sign(message, sign): '''Doc: https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dDRpeK&treeId=204&articleId=105301&docType=1''' try: OpenSSL.crypto.verify(settings.ALIPAY_PUBLIC_KEY_OBJ, sign, message, 'SHA1') return True except Exception as _: return False
# 支付寶開發者公鑰(支付寶生成) ALIPAY_PUBLIC_KEY = os.path.join(BASE_DIR, 'utils/paycenter/alipay/certs/alipay_public_key') _ALIPAY_PUBLIC_KEY_OBJ_PUB = OpenSSL.crypto.load_publickey(OpenSSL.crypto.FILETYPE_PEM, open(ALIPAY_PUBLIC_KEY).read()) _ALIPAY_PUBLIC_KEY_OBJ_X509 = OpenSSL.crypto.X509() _ALIPAY_PUBLIC_KEY_OBJ_X509.set_pubkey(_ALIPAY_PUBLIC_KEY_OBJ_PUB) ALIPAY_PUBLIC_KEY_OBJ = _ALIPAY_PUBLIC_KEY_OBJ_X509
# 支付寶開發者應用私鑰(接入方生成) ALIPAY_APP_PRIVATE_KEY = os.path.join(BASE_DIR, 'utils/paycenter/alipay/certs/alipay_app_private_key') ALIPAY_APP_PRIVATE_KEY_OBJ = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, open(ALIPAY_APP_PRIVATE_KEY).read(), None) -------------------------------------------------------------------------------------------------------------------------------------------
銀聯支付
import time import hashlib import urllib, urllib2 import base64 import OpenSSL from django.conf import settings def build_sign(param_map, sign_type="RSA"): '''構建簽名''' # 將篩選的引數按照第一個字元的鍵值ASCII碼遞增排序(字母升序排序),如果遇到相同字元則按照第二個字元的鍵值ASCII碼遞增排序,以此類推。 sort_param = sorted([(key, unicode(value, settings.UNIONPAY_ENCODING).encode(settings.UNIONPAY_ENCODING)) for key, value in param_map.iteritems()], key=lambda x: x[0]) content = '&'.join(['='.join(x) for x in sort_param]) message = hashlib.sha1(content).hexdigest() return base64.b64encode(OpenSSL.crypto.sign(settings.UNIONPAY_PRIVATE_KEY_OBJ, message, 'sha1')) def build_params(out_trade_no, total_amount): params = {} # 獲取配置資訊 params['accType'] = settings.UNIONPAY_ACC_TYPE params['accessType'] = settings.UNIONPAY_ACCESS_TYPE params['backUrl'] = settings.UNIONPAY_BACK_URL params['frontUrl'] = settings.UNIONPAY_FRONT_URL params['bizType'] = settings.UNIONPAY_BIZ_TYPE params['certId'] = settings.UNIONPAY_CERT_ID params['channelType'] = settings.UNIONPAY_CHANNEL_TYPE params['currencyCode'] = settings.UNIONPAY_CURRENCY_CODE params['encoding'] = settings.UNIONPAY_ENCODING params['merId'] = settings.UNIONPAY_MER_ID params['signMethod'] = settings.UNIONPAY_SIGN_METHOD params['txnType'] = settings.UNIONPAY_TXN_TYPE params['txnSubType'] = settings.UNIONPAY_TXN_SUBTYPE params['version'] = settings.UNIONPAY_VERSION params['orderId'] = out_trade_no params['txnAmt'] = '%d' % int(total_amount) # 單位為分 params['txnTime'] = time.strftime('%Y%m%d%H%M%S') # params['signature'] = build_sign(params) # return params return urllib.urlencode(params) def check_sign(message, sign): try: OpenSSL.crypto.verify(settings.UNIONPAY_PUBLIC_KEY_OBJ, sign, message, 'SHA1') return True except Exception as _: return False
# 商戶私鑰證書 UNIONPAY_APP_PRIVATE_KEY_CERT = os.path.join(UNIONPAY_CERTS_PATH, UNIONPAY_APP_PRIVATE_KEY_CERT_FILENAME) # PKCS12 format UNIONPAY_PRIVATE_KEYSTORE = OpenSSL.crypto.load_pkcs12(open(UNIONPAY_APP_PRIVATE_KEY_CERT).read(), UNIONPAY_APP_PRIVATE_KEY_CERT_PASSWORD) UNIONPAY_PRIVATE_KEY_OBJ = UNIONPAY_PRIVATE_KEYSTORE.get_privatekey()
# 銀聯公鑰證書 UNIONPAY_PUBLIC_KEY_CERT = os.path.join(UNIONPAY_CERTS_PATH, UNIONPAY_PUBLIC_KEY_CERT_FILENAME) UNIONPAY_PUBLIC_KEY_OBJ = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open(UNIONPAY_PUBLIC_KEY_CERT).read())