Created
March 27, 2015 02:42
-
-
Save risent/8371a8cada3ae65df567 to your computer and use it in GitHub Desktop.
UMSPay python sdk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
''' | |
Created on 2014-10-21 | |
UMSPay API | |
@author: risent | |
''' | |
import base64 | |
from binascii import unhexlify, hexlify | |
import json | |
from collections import OrderedDict | |
import M2Crypto | |
import requests | |
import ssl | |
import logging | |
from requests_toolbelt import SSLAdapter | |
class settings: | |
MER_ID = '' | |
MER_TERM_ID = '' | |
PRIVATE_KEY = '' | |
PUB_KEY = '' | |
NOTIFY_URL = '' | |
def sign(data): | |
key = M2Crypto.RSA.load_key_string(settings.PRIVATE_KEY) | |
m = M2Crypto.EVP.MessageDigest('sha1') | |
m.update(data) | |
digest = m.final() | |
signature = key.sign(digest, 'sha1') | |
return hexlify(signature) | |
def verify(data, sign): | |
bio = M2Crypto.BIO.MemoryBuffer(settings.PUB_KEY) | |
key = M2Crypto.RSA.load_pub_key_bio(bio) | |
m = M2Crypto.EVP.MessageDigest('sha1') | |
m.update(data) | |
digest = m.final() | |
return key.verify(digest, unhexlify(sign), 'sha1') == 1 | |
# UMS_GW = 'https://116.228.21.162:8603/merFrontMgr/orderBusinessServlet' | |
UMS_GW = 'https://mpos.quanminfu.com:6004/merFrontMgr/orderBusinessServlet' | |
def create_order(order): | |
''' | |
order is an instance of system Order | |
- order.created: 订单创建时间 | |
- order.price: 订单金额 | |
''' | |
params = OrderedDict() | |
params['TrasCode'] = '201201' # constant | |
params['OrderTime'] = order.created.strftime('%H%M%S') | |
params['EffectiveTime'] = '0' | |
params['OrderDate'] = order.created.strftime('%Y%m%d') | |
params['MerOrderId'] = str(order.id) | |
params['TransType'] = 'NoticePay' | |
params['TransAmt'] = str(int(order.price * 100)) | |
params['MerId'] = str(settings.MER_ID) | |
params['MerTermId'] = str(settings.MER_TERM_ID) | |
params['NotifyUrl'] = str(settings.NOTIFY_URL) | |
params['OrderDesc'] = str(order.get_name()) | |
sign_data = ''.join(params.values())[6:] | |
params['MerSign'] = sign(sign_data) | |
session = requests.Session() | |
session.mount('https://mpos.quanminfu.com:6004', | |
SSLAdapter(ssl.PROTOCOL_SSLv3)) | |
req = session.post(UMS_GW, | |
data={'jsonString': json.dumps(params)}, | |
verify=False) | |
result = req.json() | |
result['merSign'] = sign(str(result['TransId'] + result['ChrCode'])) | |
result['id'] = order.id | |
return result | |
# Django notify view | |
def umspay_order_notify_url(request, *args, **kwargs): | |
from django.http import HttpResponse | |
from order.models import Order | |
data = request.POST.copy() | |
order_time = data['OrderTime'] | |
order_date = data['OrderDate'] | |
mer_order_id = data['MerOrderId'] | |
trans_type = data['TransType'] | |
trans_amt = data['TransAmt'] | |
mer_id = data['MerId'] | |
mer_term_id = data['MerTermId'] | |
trans_id = data['TransId'] | |
trans_state = data['TransState'] | |
ref_id = data['RefId'] | |
account = data['Account'] | |
trans_desc = data['TransDesc'] #optional | |
reserve = data.get('Reserve') | |
sign_keys = ["OrderTime", "OrderDate", "MerOrderId", "TransType", | |
"TransAmt", "MerId", "MerTermId", "TransId", "TransState", | |
"RefId", "Account", "TransDesc", "Reserve"] | |
params = OrderedDict() | |
for key in sign_keys: | |
params[key] = data.get(key) | |
verify_data = ''.join(params.values()) | |
signature = data.get('Signature') | |
if verify(str(verify_data), str(signature)): | |
# UMSPay verify success | |
order = Order.objects.get(id=int(mer_order_id)) | |
if trans_state == '1': | |
# paid success | |
order.state = PAID | |
order.pay_date = datetime.now() | |
order.save() | |
data['MerPlatTime'] = datetime.now().strftime('%Y%m%d%H%M%S') | |
data['MerOrderState'] = '00' | |
response_keys = ["MerOrderId", "TransType", "MerId", "MerTermId", | |
"TransId", "MerPlatTime", "MerOrderState"] | |
response_data = OrderedDict() | |
for key in response_keys: | |
response_data[key] = data[key] | |
sign_data = ''.join(response_data.values()) | |
mer_sign = sign(sign_data) | |
response_data['MerSign'] = mer_sign | |
response_data['TransCode'] = '201202' | |
logger.info('UMSPay notify return success') | |
return HttpResponse(json.dumps(response_data)) | |
else: | |
logger.info( | |
'---UMSPay failed state for order: %s ' % int(mer_order_id)) | |
return HttpResponse('no') | |
else: | |
logger.info( | |
'---UMSPay verify failed for order: %s ' % int(mer_order_id)) | |
return HttpResponse('fail') | |
def umspay_order_return_url(request, *args, **kwargs): | |
from django.http import HttpResponseRedirect | |
from order.models import Order | |
order_id = request.GET.get('merchantOrderId') | |
resp_code = request.GET.get('respCode') | |
order = Order.objects.get(id=int(order_id)) | |
if resp_code == '0000': | |
logger.info('---UMSPay GET return ') | |
else: | |
logger.info('---UMSPay GET return verify fail') | |
return_url = '' # Order detail url | |
return HttpResponseRedirect(return_url) | |
''' | |
Django usage | |
`payment_tags.py | |
@register.filter | |
def umspay_order(order): | |
"""UMSPay filter""" | |
from payment.umspay import create_order | |
return create_order(order) | |
`payment.html | |
{% load payment_tags %} | |
<div class="combo-pay mod_cell" id="paylink"> | |
<div class="bd"> | |
{% with order=current_order|umspay_order %} | |
<form action="https://mpos.quanminfu.com:8018/umsFrontWebQmjf/umspay" method="POST"> | |
<input id="chrCode" name="chrCode" type="hidden" value="{{ order.ChrCode }}"/> | |
<input id="tranId" name="tranId" type="hidden" value="{{ order.TransId }}"/> | |
<input id="merSign" name="merSign" type="hidden" value="{{ order.merSign }}"/> | |
<input id="url" name="url" type="hidden" value="http://{{ request.get_host }}{% url 'umspay_order_return' %}"/> | |
<div class="order-topay fn-ml-20"><input class="noact-btn btn_block btn_strong mod_btn" type="submit" value="确定支付"></div> | |
</form> | |
{% endwith %} | |
</div> | |
</div> | |
''' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment