This article mainly introduces relevant information about the development process of WeChat payment. Friends who need it can refer to it
Note that I am using the payment of the WeChat open platform, which is related to the mobile app and not to the public. The account is irrelevant.
The main operation process of WeChat payment
1. The user browses the app, selects the product and places an order.
2. The server processes the order logic and starts the formal payment process
3. First, the backend server initiates a request to the weixin server to obtain a token.
4. The backend server gets the token, encrypts it with other parameters, and initiates a request to the weixin server again to obtain a prepayment prepayid
5. The backend server returns the prepayid to the app client
6. The app calls the WeChat control on the mobile phone to complete the payment process.
7.app initiates a callback request to the backend server to notify the server that the transaction is completed.
8. After the weixin server has processed all the processes, it initiates a post request to the backend server to formally notify the backend server that the transaction is completed
Some of the above processes Note:
1. The token obtained each time has a time limit, the default is 7200s, and it can be obtained up to 200 times a day, so it is best to put it in redisCache Get it up again after it expires
2. The callback initiated by the app is unreliable by default. The background should try its best (but not necessarily) to initiate an order to the WeChat serverquery, query the results of this transaction.
3. The notify initiated by the weixin server to the background is the final barrier to ensure the completion of the transaction. The background server must return "success" after confirmation, otherwise the weixin server will try to resend the request.
Get token
This step is very simple, just send a get request. Just configure the correct parameters.
‘‘‘从微信服务器获取token‘‘‘ def _getAccessTokenFromWeixin(self): response = requests.get(self.tokenUrl % (self.appId, self.appSecret)) if response.status_code == 200: text = response.text tokenInfo = json.loads(text) try: token = tokenInfo[‘access_token‘] expires_in = tokenInfo[‘expires_in‘] self._writeWeixinTokenLog(token, self.order_no) return token except KeyError: return None #token获取失败 return None #http请求失败
Get prepayid
In the development process of WeChat Pay, the most tedious thing is to get the prepayid.
In this step we need to assemble such a parameter:
{ "appid":"wxd930ea5d5a258f4f", "traceid":"test_1399514976", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb ", "timestamp":1399514976, "package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8", "sign_method":"sha1", "app_signature":"7f77b507b755b3262884291517e380f8" }
##Assemble package
Here The first step is to assemble the package:"package":"bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF% 95&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_ no=7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1& total_fee=1&sign=7F77B507B755B3262884291517E380F8",
string. Note that these keys do not include sign
2. In the above Splice key=paternerKey after the string, thenmd5 sign the entire string, and then convert it to uppercase. At this time we get the signature
Then we urlencode the values of all params Convert it and then splice it with sign=signValue to get the package string. The process of creating MD5 here is as follows:def createMD5Signature(self, signParams): ‘‘‘先排序‘‘‘ sortedParams = sorted(signParams.iteritems(), key=lambda d:d[0]) ‘‘‘拼接‘‘‘ stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams if item[0] != ‘sign‘ and ‘‘ != item[1]]) #加上财付通商户权限密钥 stringSignTemp += ‘&key=%s‘ % (self.partnerKey) #使用MD5进行签名,然后转化为大写 stringSign = hashlib.md5(stringSignTemp).hexdigest().upper() #Upper return stringSign
def getPackage(self, packageParams): ‘‘‘先获取params的sign,然后将params进行urlencode,最后拼接,加上sign‘‘‘ sign = self.createMD5Signature(packageParams) packageParams = sorted(packageParams.iteritems(), key=lambda d:d[0]) stringParams = "&".join(["%s=%s" % (item[0], urllib.quote(str(item[1]))) for item in packageParams]) stringParams += ‘&sign=%s‘ % (sign) return stringParams
Continue to assemble the parameters
After getting the package, we continue to assemble the parameters:The parameters required here are:appid=wxd930ea5d5a258f4f appkey=L8LrMqqeGRxST5reouB0K66CaY A WpqhA Vsq7ggKkxHCOastWksvuX1uvmvQcl xaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K noncestr=e7d161ac8d8a76529d39d9f5b4249ccb package=bank_type=WX&body=%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95 &fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fweixin.qq.com&out_trade_no =7240b65810859cbf2a8d9f76a638c0a3&partner=1900000109&spbill_create_ip=196.168.1.1&tot al_fee=1&sign=7F77B507B755B3262884291517E380F8 timestamp=1399514976
are involved in the signature, but the last parameter The appKey is not included. Remember to delete after signing.
1. Sort all parameters in lexicographic order, and then splice them 2. Perform sha1 signature and splice them to the end of the above string 3. Pay attention to the following Delete the appKey, and then add signThe code to obtain the sha1 signature is as follows:def createSHA1Signature(self, params): ‘‘‘先排序,然后拼接‘‘‘ sortedParams = sorted(params.iteritems(), key=lambda d:d[0]) stringSignTemp = "&".join(["%s=%s" % (item[0], item[1]) for item in sortedParams]) stringSign = hashlib.sha1(stringSignTemp).hexdigest() return stringSign
{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
‘‘‘获取预支付prepayid‘‘‘ def gerPrepayId(self, token, requestParams): ‘‘‘将参数,包括package,进行json化,然后发起post请求‘‘‘ data = json.dumps(requestParams) response = requests.post(self.gateUrl % (token), data=data) if response.status_code == 200: text = response.text text = json.loads(text) errcode = text[‘errcode‘] if errcode == 0: return text[‘prepayid‘] return None
Sign again
Here we use the above sha1 signature method to sign again and obtain the following parameters:{ "appid":"wxd930ea5d5a258f4f", "noncestr":"e7d161ac8d8a76529d39d9f5b4249ccb", "package":"Sign=WXpay"; "partnerid":"1900000109" "prepayid":"1101000000140429eb40476f8896f4c9", "sign":"7ffecb600d7157c5aa49810d2d8f28bc2811827b", "timestamp":"1399514976" }
‘‘‘接收app的请求,返回prepayid‘‘‘ class WeixinRequirePrePaidHandler(BasicTemplateHandler): ‘‘‘这个方法在OrdersAddHandler中被调用‘‘‘ @staticmethod def getPrePaidResult(order_no, total_pay, product_name, client_ip): ‘‘‘封装了常用的签名算法‘‘‘ weixinRequestHandler = WeixinRequestHandler(order_no) ‘‘‘收集订单相关信息‘‘‘ addtion = str(random.randint(10, 100)) #产生一个两位的数字,拼接在订单号的后面 out_trade_no = str(order_no) + addtion order_price = float(total_pay) #这里必须允许浮点数,后面转化成分之后转化为int #order_price = 0.01 #测试 remote_addr = client_ip #客户端的IP地址 print remote_addr current_time = int(time.time()) order_create_time = str(current_time) order_deadline = str(current_time + 20*60) ‘‘‘这里的一些参数供下面使用‘‘‘ noncestr = hashlib.md5(str(random.random())).hexdigest() timestamp = str(int(time.time())) pack = ‘Sign=WXPay‘ ‘‘‘获取token‘‘‘ access_token = weixinRequestHandler.getAccessToken() logging.info("get token: %s" % access_token) if access_token: ‘‘‘设置package参数‘‘‘ packageParams = {} packageParams[‘bank_type‘] = ‘WX‘ #支付类型 packageParams[‘body‘] = product_name #商品名称 packageParams[‘fee_type‘] = ‘1‘ #人民币 fen packageParams[‘input_charset‘] = ‘GBK‘ #GBK packageParams[‘notify_url‘] = config[‘notify_url‘] #post异步消息通知 packageParams[‘out_trade_no‘] = str(out_trade_no) #订单号 packageParams[‘partner‘] = config[‘partnerId‘] #商户号 packageParams[‘total_fee‘] = str(int(order_price*100)) #订单金额,单位是分 packageParams[‘spbill_create_ip‘] = remote_addr #IP packageParams[‘time_start‘] = order_create_time #订单生成时间 packageParams[‘time_expire‘] = order_deadline #订单失效时间 ‘‘‘获取package‘‘‘ package = weixinRequestHandler.getPackage(packageParams) ‘‘‘设置支付参数‘‘‘ signParams = {} signParams[‘appid‘] = config[‘appId‘] signParams[‘appkey‘] = config[‘paySignKey‘] #delete signParams[‘noncestr‘] = noncestr signParams[‘package‘] = package signParams[‘timestamp‘] = timestamp signParams[‘traceid‘] = ‘mytraceid_001‘ ‘‘‘生成支付签名‘‘‘ app_signature = weixinRequestHandler.createSHA1Signature(signParams) ‘‘‘增加不参与签名的额外参数‘‘‘ signParams[‘sign_method‘] = ‘sha1‘ signParams[‘app_signature‘] = app_signature ‘‘‘剔除appKey‘‘‘ del signParams[‘appkey‘] ‘‘‘获取prepayid‘‘‘ prepayid = weixinRequestHandler.gerPrepayId(access_token, signParams) if prepayid: ‘‘‘使用拿到的prepayid再次准备签名‘‘‘ pack = ‘sign=WXPay‘ prepayParams = {} prepayParams[‘appid‘] = config[‘appId‘] prepayParams[‘appkey‘] = config[‘paySignKey‘] prepayParams[‘noncestr‘] = noncestr prepayParams[‘package‘] = pack prepayParams[‘partnerid‘] = config[‘partnerId‘] prepayParams[‘prepayid‘] = prepayid prepayParams[‘timestamp‘] = timestamp ‘‘‘生成签名‘‘‘ sign = weixinRequestHandler.createSHA1Signature(prepayParams) ‘‘‘准备输出参数‘‘‘ returnParams = {} returnParams[‘status‘] = 0 returnParams[‘retmsg‘] = ‘success‘ returnParams[‘appid‘] = config[‘appId‘] returnParams[‘noncestr‘] = noncestr returnParams[‘package‘] = pack returnParams[‘prepayid‘] = prepayid returnParams[‘timestamp‘] = timestamp returnParams[‘sign‘] = sign returnParams[‘partnerId‘] = config[‘partnerId‘] returnParams[‘addtion‘] = addtion else: ‘‘‘prepayid获取失败‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘prepayid获取失败‘ else: ‘‘‘token获取失败‘‘‘ returnParams = {} returnParams[‘status‘] = -1 returnParams[‘retmsg‘] = ‘token获取失败‘ ‘‘‘生成json格式文本,然后返回给APP‘‘‘ return returnParams
Background asynchronous notification
Sent from WeChat server The notify asynchronous notification is the final sign of successful payment. Forsecurity reasons, we must extend the signature:
The extension code is as follows:def isTenpaySign(self, params): helper = WeixinRequestHandler() sign = helper.createMD5Signature(params) return params[‘sign‘] == sign
‘‘‘微信服务器向后台发送的异步通知‘‘‘ class WeixinAppNotifyHandler(BasicTemplateHandler): def initialize(self): self.weixinResponseHandler = WeixinResponseHandler() def post(self): ‘‘‘解析参数‘‘‘ params = self.parseQueryString() ‘‘‘验证是否是weixin服务器发回的消息‘‘‘ verifyWeixinSign = self.weixinResponseHandler.isTenpaySign(params) ‘‘‘处理订单‘‘‘ if verifyWeixinSign: ‘‘‘订单逻辑‘‘‘ order_no = str(params[‘out_trade_no‘]) order_no = order_no[0:-2] print ‘%s paied successfully‘ % order_no self.saveWeixinReceipt(params) updateOrdersPaidByWeixin(order_no) #更新订单使用状态 consumeCouponByOrderNo(order_no) #优惠券已经使用 self.write("success") else: self.write("fail") def parseQueryString(self): ‘‘‘获取url中所有的参数‘‘‘ uri = self.request.uri ‘‘‘解析出URI中的query字符串‘‘‘ parseResult = urlparse.urlparse(uri) query = parseResult.query ‘‘‘解析query字符串‘‘‘ params = urlparse.parse_qs(query) for item in params: params[item] = params[item][0].strip() return params
Finally, the payment is not considered successful when the user completes the payment on the mobile phone. Only when the weixin server receives the success returned by the notify notification, the transaction is finally considered successful. At this time, our mobile phone can receive the official WeChat message. A message came.
The above is a compilation of information on the WeChat payment development process. We will continue to add relevant information in the future. Thank you for your support of this site!
The above is the detailed content of Detailed introduction to the development process of WeChat Pay. For more information, please follow other related articles on the PHP Chinese website!