Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Romain Courteaud
slapos.core
Commits
fca2f842
Commit
fca2f842
authored
5 years ago
by
Boxiang Sun
Committed by
Rafael Monnerat
5 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos_subscription_request: Real Wechat Payment in purchase step
parent
042bd6bc
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
144 additions
and
48 deletions
+144
-48
master/bt5/slapos_subscription_request/ExtensionTemplateItem/portal_components/extension.erp5.WechatUtils.py
...plateItem/portal_components/extension.erp5.WechatUtils.py
+69
-42
master/bt5/slapos_subscription_request/ExtensionTemplateItem/portal_components/extension.erp5.WechatUtils.xml
...lateItem/portal_components/extension.erp5.WechatUtils.xml
+2
-3
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/Base_generateWechatQRCodeFromCodeURL.py
...scription_request/Base_generateWechatQRCodeFromCodeURL.py
+0
-1
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/Base_generateWechatQRCodeFromCodeURL.xml
...cription_request/Base_generateWechatQRCodeFromCodeURL.xml
+1
-1
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/ERP5Site_getWechatPaymentConfiguration.py
...ription_request/ERP5Site_getWechatPaymentConfiguration.py
+1
-0
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/ERP5Site_getWechatPaymentConfiguration.xml
...iption_request/ERP5Site_getWechatPaymentConfiguration.xml
+62
-0
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/SubscriptionRequestModule_requestSubscriptionProxy.py
...est/SubscriptionRequestModule_requestSubscriptionProxy.py
+9
-1
No files found.
master/bt5/slapos_subscription_request/ExtensionTemplateItem/portal_components/extension.erp5.WechatUtils.py
View file @
fca2f842
import
random
,
string
,
hashlib
,
urllib2
import
random
,
string
,
hashlib
,
urllib2
,
socket
from
urlparse
import
urlparse
try
:
import
xml.etree.cElementTree
as
ET
except
ImportError
:
...
...
@@ -8,28 +9,12 @@ class WechatException(Exception):
def
__init__
(
self
,
msg
):
super
(
WechatException
,
self
).
__init__
(
msg
)
# RapidSpace Wechat acocunt configuration
class
Single
(
object
):
_instance
=
None
PAYMENT_DONE
=
False
def
__new__
(
cls
,
*
args
,
**
kw
):
if
cls
.
_instance
is
None
:
cls
.
_instance
=
object
.
__new__
(
cls
,
*
args
,
**
kw
)
return
cls
.
_instance
def
__init__
(
self
):
pass
def
finishThePayment
(
self
):
self
.
APP_ID
=
"XXX"
APP_ID
=
"wxadebca31430703b0"
# Wechat public account appid
MCH_ID
=
""
# Wechat merchant account ID
API_KEY
=
""
# Wechat merchant platform(pay.weixin.qq.com) -->账户设置 -->API安全 -->密钥设置
CREATE_IP
=
""
# The IP address which request the order to Wechat, aka: instance IP
# UFDODER_URL = "https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder" # Wechat unified order API
UFDODER_URL
=
"https://api.mch.weixin.qq.com/pay/unifiedorder"
# Wechat unified order API
NOTIFY_URL
=
"your IP: port/Method"
# Wechat payment callback method
QUERY_URL
=
"https://api.mch.weixin.qq.com/pay/orderquery"
QUERY_URL
=
"https://api.mch.weixin.qq.com/
sandboxnew/
pay/orderquery"
def
generateRandomStr
(
random_length
=
24
):
...
...
@@ -81,8 +66,9 @@ def convert_xml_to_dict(xml_content):
return
dict_content
def
convert_dict_to_xml
(
dict_content
):
dict_content
[
'sign'
]
=
calculateSign
(
dict_content
,
API_KEY
)
def
convert_dict_to_xml
(
self
,
dict_content
):
wechat_account_configuration
=
self
.
ERP5Site_getWechatPaymentConfiguration
()
dict_content
[
'sign'
]
=
calculateSign
(
dict_content
,
wechat_account_configuration
[
'API_KEY'
])
xml
=
''
for
key
,
value
in
dict_content
.
items
():
xml
+=
'<{0}>{1}</{0}>'
.
format
(
key
,
value
)
...
...
@@ -90,16 +76,48 @@ def convert_dict_to_xml(dict_content):
return
xml
def
getWechatQRCodeURL
(
self
,
order_id
,
price
,
amount
):
product_name
=
"Pre-order "
+
amount
+
" RapidSpace VM "
return
def
getSandboxKey
(
self
):
SANDBOX_KEY_URL
=
"https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"
wechat_account_configuration
=
self
.
ERP5Site_getWechatPaymentConfiguration
()
params
=
{}
params
[
'mch_id'
]
=
wechat_account_configuration
[
'MCH_ID'
]
params
[
'nonce_str'
]
=
generateRandomStr
()
params
[
'sign'
]
=
calculateSign
(
params
,
wechat_account_configuration
[
'API_KEY'
])
# construct XML str
request_xml_str
=
'<xml>'
for
key
,
value
in
params
.
items
():
if
isinstance
(
value
,
basestring
):
request_xml_str
=
'%s<%s><![CDATA[%s]]></%s>'
%
(
request_xml_str
,
key
,
value
,
key
,
)
else
:
request_xml_str
=
'%s<%s>%s</%s>'
%
(
request_xml_str
,
key
,
value
,
key
,
)
request_xml_str
=
'%s</xml>'
%
request_xml_str
result
=
urllib2
.
Request
(
SANDBOX_KEY_URL
,
data
=
request_xml_str
)
result_data
=
urllib2
.
urlopen
(
result
)
result_read
=
result_data
.
read
()
result_dict_content
=
convert_xml_to_dict
(
result_read
)
return_code
=
result_dict_content
.
get
(
'return_code'
,
''
)
if
return_code
==
"SUCCESS"
:
result_msg
=
result_dict_content
[
'return_msg'
]
if
result_msg
==
"ok"
:
sandbox_signkey
=
result_dict_content
[
'sandbox_signkey'
]
return
sandbox_signkey
raise
Exception
(
result_dict_content
[
'result_msg'
].
encode
(
'utf-8'
))
raise
Exception
(
"Get sanbox key failed: "
+
str
(
result_dict_content
))
# TODO: waiting for the APP_ID
appid
=
APP_ID
# XXXXXXXXXXXXXXXXXXXXXXXXXXxx
mch_id
=
MCH_ID
key
=
API_KEY
def
getWechatQRCodeURL
(
self
,
order_id
,
price
,
amount
):
portal
=
self
.
getPortalObject
()
base_url
=
portal
.
absolute_url
()
NOTIFY_URL
=
base_url
+
"/Base_receiveWechatPaymentNotify"
# Wechat payment callback method
wechat_account_configuration
=
self
.
ERP5Site_getWechatPaymentConfiguration
()
appid
=
wechat_account_configuration
[
'APP_ID'
]
mch_id
=
wechat_account_configuration
[
'MCH_ID'
]
key
=
wechat_account_configuration
[
'API_KEY'
]
# This is for sandbox test
# key = getSandboxKey() # API_KEY
nonce_str
=
generateRandomStr
()
spbill_create_ip
=
CREATE_IP
result
=
urlparse
(
base_url
)
spbill_create_ip
=
socket
.
gethostbyname
(
result
.
netloc
)
notify_url
=
NOTIFY_URL
trade_type
=
"NATIVE"
...
...
@@ -109,14 +127,16 @@ def getWechatQRCodeURL(self, order_id, price, amount):
params
[
'mch_id'
]
=
mch_id
params
[
'nonce_str'
]
=
nonce_str
params
[
'out_trade_no'
]
=
order_id
.
encode
(
'utf-8'
)
params
[
'total_fee'
]
=
amount
*
100
# unit is Fen, 1 CHY = 100 Fen
# This is for sandbox test, sandbox need the total_fee equal to 101 exactly
# params['total_fee'] = 101 # int(-(price * 100)) # unit is Fen, 1 CHY = 100 Fen
params
[
'total_fee'
]
=
int
(
-
(
price
*
100
))
# unit is Fen, 1 CHY = 100 Fen
params
[
'spbill_create_ip'
]
=
spbill_create_ip
params
[
'notify_url'
]
=
notify_url
params
[
'body'
]
=
product_name
.
encode
(
'utf-8'
)
params
[
'body'
]
=
"Rapid Space VM machine"
.
encode
(
'utf-8'
)
params
[
'trade_type'
]
=
trade_type
# generate signature
params
[
'sign'
]
=
calculateSign
(
params
,
API_KEY
)
params
[
'sign'
]
=
calculateSign
(
params
,
key
)
# construct XML str
request_xml_str
=
'<xml>'
...
...
@@ -137,11 +157,11 @@ def getWechatQRCodeURL(self, order_id, price, amount):
result_code
=
result_dict_content
[
'result_code'
]
if
result_code
==
"SUCCESS"
:
code_url
=
result_dict_content
[
'code_url'
]
return
"weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00"
return
code_url
else
:
print
(
"Error description: {0}"
.
format
(
result_dict_content
.
get
(
"err_code_des"
)))
raise
Exception
(
"Error description: {0}"
.
format
(
result_dict_content
.
get
(
"err_code_des"
)))
else
:
print
(
"Error description: {0}"
.
format
(
result_dict_content
.
get
(
"return_msg"
)))
raise
Exception
(
"Error description: {0}"
.
format
(
result_dict_content
.
get
(
"return_msg"
)))
def
receiveWechatPaymentNotify
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
@@ -167,11 +187,18 @@ def receiveWechatPaymentNotify(self, request, *args, **kwargs):
<transaction_id><![CDATA[4200000031201712112434025551875]]></transaction_id>
</xml>
'''
return
'''
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
'''
wechat_account_configuration
=
self
.
ERP5Site_getWechatPaymentConfiguration
()
params
=
convert_xml_to_dict
(
request
.
body
)
if
params
.
get
(
"return_code"
)
==
"SUCCESS"
:
# Connection is ok
sign
=
params
.
pop
(
'sign'
)
recalcualted_sign
=
calculateSign
(
params
,
API_KEY
)
recalcualted_sign
=
calculateSign
(
params
,
wechat_account_configuration
[
'API_KEY'
]
)
if
recalcualted_sign
==
sign
:
if
params
.
get
(
"result_code"
,
None
)
==
"SUCCESS"
:
# payment is ok
pass
...
...
@@ -202,20 +229,20 @@ def queryWechatOrderStatus(self, dict_content):
- transaction_id (str): wechat order number, use this in higher priority, it will return in the payment notify callback
- out_trade_no(str): The order ID used inside ERP5, less than 32 characters, digits, alphabets, and "_-|*@", unique in ERP5
'''
if
APP_ID
==
"XXX"
:
return
"SUCCESS"
return
"XXXS"
if
"transaction_id"
not
in
dict_content
and
"out_trade_no"
not
in
dict_content
:
raise
WechatException
(
"transaction_id or out_trade_no is needed for query the Wechat Order"
)
wechat_account_configuration
=
self
.
ERP5Site_getWechatPaymentConfiguration
()
params
=
{
"appid"
:
APP_ID
,
"mch_id"
:
MCH_ID
,
"appid"
:
wechat_account_configuration
[
'APP_ID'
]
,
"mch_id"
:
wechat_account_configuration
[
'MCH_ID'
]
,
"nonce_str"
:
generateRandomStr
(),
"transaction_id"
:
dict_content
.
get
(
"transaction_id"
,
""
),
"out_trade_no"
:
dict_content
.
get
(
"out_trade_no"
,
""
),
}
sign
=
calculateSign
(
params
,
API_KEY
)
sign
=
calculateSign
(
params
,
wechat_account_configuration
[
'API_KEY'
]
)
params
[
"sign"
]
=
sign
# xml_str = convert_dict_to_xml(params)
return
None
...
...
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/ExtensionTemplateItem/portal_components/extension.erp5.WechatUtils.xml
View file @
fca2f842
...
...
@@ -46,9 +46,8 @@
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple>
<string>
W: 27, 0: Cannot decode using encoding "ascii", unexpected byte at position 63 (invalid-encoded-data)
</string>
<string>
W: 98, 2: Unreachable code (unreachable)
</string>
<string>
W:139, 6: Unused variable \'code_url\' (unused-variable)
</string>
<string>
W:196, 2: Unreachable code (unreachable)
</string>
<string>
W:233, 2: Unreachable code (unreachable)
</string>
</tuple>
</value>
</item>
...
...
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/Base_generateWechatQRCodeFromCodeURL.py
View file @
fca2f842
# inspired by Pack_generateCode128BarcodeImage in sanef-evl project
code_url
=
code_url
+
"&trade_no="
+
trade_no
return
context
.
Base_generateBarcodeImage
(
'qrcode'
,
code_url
)
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/Base_generateWechatQRCodeFromCodeURL.xml
View file @
fca2f842
...
...
@@ -50,7 +50,7 @@
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string>
code_url
, trade_no
</string>
</value>
<value>
<string>
code_url
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
...
...
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/ERP5Site_getWechatPaymentConfiguration.py
0 → 100644
View file @
fca2f842
return
{}
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/ERP5Site_getWechatPaymentConfiguration.xml
0 → 100644
View file @
fca2f842
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"PythonScript"
module=
"Products.PythonScripts.PythonScript"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
Script_magic
</string>
</key>
<value>
<int>
3
</int>
</value>
</item>
<item>
<key>
<string>
_bind_names
</string>
</key>
<value>
<object>
<klass>
<global
name=
"NameAssignments"
module=
"Shared.DC.Scripts.Bindings"
/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key>
<string>
_asgns
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
name_container
</string>
</key>
<value>
<string>
container
</string>
</value>
</item>
<item>
<key>
<string>
name_context
</string>
</key>
<value>
<string>
context
</string>
</value>
</item>
<item>
<key>
<string>
name_m_self
</string>
</key>
<value>
<string>
script
</string>
</value>
</item>
<item>
<key>
<string>
name_subpath
</string>
</key>
<value>
<string>
traverse_subpath
</string>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
_params
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
ERP5Site_getWechatPaymentConfiguration
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This diff is collapsed.
Click to expand it.
master/bt5/slapos_subscription_request/SkinTemplateItem/portal_skins/slapos_subscription_request/SubscriptionRequestModule_requestSubscriptionProxy.py
View file @
fca2f842
...
...
@@ -43,9 +43,17 @@ payment = person.Person_restrictMethodAsShadowUser(
if
batch_mode
:
return
{
'subscription'
:
subscription_request
.
getRelativeUrl
(),
'payment'
:
payment
.
getRelativeUrl
()
}
def
wrapGetPriceWithShadow
(
payment
):
return
payment
.
PaymentTransaction_getTotalPayablePrice
()
price
=
person
.
Person_restrictMethodAsShadowUser
(
shadow_document
=
person
,
callable_object
=
wrapGetPriceWithShadow
,
argument_list
=
[
payment
,])
if
payment_mode
==
"wechat"
:
portal
=
context
.
getPortalObject
()
code_url
=
portal
.
Base_getWechatCodeURL
(
subscription_request
.
getId
(),
p
ayment
.
PaymentTransaction_getTotalPayablePrice
()
,
user_input_dict
[
"amount"
])
code_url
=
portal
.
Base_getWechatCodeURL
(
subscription_request
.
getId
(),
p
rice
,
user_input_dict
[
"amount"
])
web_site
=
context
.
getWebSiteValue
()
base_url
=
web_site
.
absolute_url
()
return
context
.
REQUEST
.
RESPONSE
.
redirect
(
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment