main body (of a book)
Because recently they are doing small program payments, here is a brief introduction to talk about using python to do small program payments this process. Of course, before proceeding with the development is still recommended to read the specific process, clear payment process.
1. Payment Interaction Flow
Of course, you can refer to the official documentation for specific parameter configurations/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
2. Get openid (WeChat user identification)
import requests from config import APPID, SECRET class OpenidUtils(object): def __init__(self, jscode): = "/sns/jscode2session" = APPID # applet id = SECRET # Don't confuse it with the key to pay later # = jscode # Dynamic jscode passed back from the front end def get_openid(self): # url must be spliced, not passed as a parameter url = + "?app&secret=" + + "&js_code=" + + "&grant_type=authorization_code" r = (url) print(()) openid = ()['openid'] return openid
3. Payment requests
# -*- coding:utf-8 -*- import requests import hashlib import xmltodict import time import random import string import urllib2 import sys class WX_PayToolUtil(): """ WeChat Payment Tools """ def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL): self._APP_ID = APP_ID # Applet ID self._MCH_ID = MCH_ID # # Merchant number self._API_KEY = API_KEY self._UFDODER_URL = "/pay/unifiedorder" # Interface links self._NOTIFY_URL = NOTIFY_URL # Asynchronous notifications def generate_sign(self, param): '''Generate Signature''' stringA = '' ks = sorted(()) # Parameter ordering for k in ks: stringA += (k + '=' + param[k] + '&') # Splice Merchant KEY stringSignTemp = stringA + "key=" + self._API_KEY # md5 encryption, or you can use other methods. hash_md5 = hashlib.md5(('utf8')) sign = hash_md5.hexdigest().upper() return sign ''' # python2 another implementation def generate_sign(self, params): ret = [] for k in sorted(()): if (k != 'sign') and (k != '') and (params[k] is not None): ('%s=%s' % (k, params[k])) params_str = '&'.join(ret) params_str = '%(params_str)s&key=%(partner_key)s' % {'params_str': params_str, 'partner_key': key} reload(sys) ('utf8') params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest() sign = params_str.upper() return sign ''' def getPayUrl(self, orderid, openid, goodsPrice, **kwargs): """Make a request to wechatpay to get the url""" key = self._API_KEY nonce_str = ''.join(( + , 30)) # Generate random strings, less than 32 bits params = { 'appid': self._APP_ID, # Applet ID 'mch_id': self._MCH_ID, # Merchant Number 'nonce_str': nonce_str, # Random strings "body": 'Test Order', # Payment instructions 'out_trade_no': orderid, # Order number generated 'total_fee': str(goodsPrice), # Bid amount 'spbill_create_ip': "127.0.0.1", # Applet can't get client ip, web implemented with socekt 'notify_url': self._NOTIFY_URL, 'trade_type': "JSAPI", # Type of payment "openid": openid, # user id } # Signature generation params['sign'] = self.generate_sign(params) # python3 one way to write param = {'root': params} xml = (param) response = (self._UFDODER_URL, data=('utf-8'), headers={'Content-Type': 'text/xml'}) # xml 2 dict msg = xmlmsg = (msg) # 4. Get prepay_id if xmlmsg['xml']['return_code'] == 'SUCCESS': if xmlmsg['xml']['result_code'] == 'SUCCESS': prepay_id = xmlmsg['xml']['prepay_id'] # Time stamp timeStamp = str(int(())) # 5. five parameters data = { "appId": self._APP_ID, "nonceStr": nonce_str, "package": "prepay_signType": 'MD5', "timeStamp": timeStamp, } # 6. paySign signature paySign = self.generate_sign(data) data["paySign"] = paySign # Add signature # 7. Signed parameters passed to the front end return data # python2 one way to write ''' request_xml_str = '<xml>' for key, value in (): if isinstance(value, str): 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 # Make a request to WeChat Pay and fetch the return data res = (self._UFDODER_URL, data=request_xml_str.encode("utf-8")) res_data = (res) res_read = res_data.read() doc = (res_read) return_code = doc['xml']['return_code'] if return_code == "SUCCESS": result_code = doc['xml']['result_code'] if result_code == "SUCCESS": doc = doc['xml'] data = { "appId": self._APP_ID, "nonceStr": nonce_str, "package": "prepay_prepay_id"], "signType": 'MD5', "timeStamp": str(int(())), } # paySign signatures paySign = self.generate_sign(data) data["paySign"] = paySign # Add signature return data else: err_des = doc['xml']['err_code_des'] return err_des else: fail_des = doc['xml']['return_msg'] return fail_des '''
Of course you may encounter the error has a signature error, the general situation is that your appSecret and merchant number of the API key two get it wrong, of course, if not there may be other problems, solution linkhttps:///article/ 。
Other payment methods to get the user's ip address can be obtained through the (()) method.
4. Payment callback
# Harmonize order callback processing import xmltodict from import HttpResponse def payback(request): msg = ('utf-8') xmlmsg = (msg) return_code = xmlmsg['xml']['return_code'] if return_code == 'FAIL': # An official error has been issued return HttpResponse("""<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[Signature_Error]]></return_msg></xml>""", content_type='text/xml', status=200) elif return_code == 'SUCCESS': # Get the order number for this payment out_trade_no = xmlmsg['xml']['out_trade_no'] # Process business logic as needed return HttpResponse("""<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>""", content_type='text/xml', status=200)
Of course, there are a lot of parameters for WeChat callbacks that you can refer to in detail./wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
In the callback time may encounter such a problem, after the successful payment did not call the callback function, it is possible that the callback address is https and then changed to http on the line, encountered this pit, the specific reasons do not know. The server does not block https access, https certificate is not a problem, change https to http last.
5. Security issues
In the process of using the merchant system for the content of the payment result notification must be done to verify the signature and check whether the returned order amount is the same as the merchant side of the order amount, to prevent data leakage leading to the emergence of "false notification", resulting in loss of funds.
My solution in the development process is to initiate a request to the WeChat payment terminal, the order number, amount, signature, etc. into the database, and then in the callback function there to verify the judgment. In the case of confirming the same situation with the previous order, before proceeding to a series of subsequent operations.
And finally, a blessing for all of you
# _oo8oo_ # o8888888o # 88" . "88 # (| -_- |) # 0\ = /0 # ___/'==='\___ # .' \\| |# '. # / \\||| : |||# \ # / _||||| -:- |||||_ \ # | | \\\ - #/ | | # | \_| ''\---/'' |_/ | # \ .-\__ '-' __/-. / # ___'. .' /-.-\ '. .'___ # ."" '< '.___\_<|>_/___.' >' "". # | | : `- \`.:`\ _ /`:.`/ -` : | | # \ \ `-. \_ __\ /__ _/ .-` / / # =====`-.____`.___ \_____/ ___.`____.-`===== # `=---=` # # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # #
summarize
The above is a small introduction to the Python implementation of WeChat small program payment function, I hope to help you, if you have any questions please leave me a message, I will reply to you in a timely manner. I would also like to thank you very much for your support of my website!
If you find this article helpful, please feel free to reprint it, and please note the source, thank you!