微信小程序之微信支付(Django)
小程序端:
wx.login({ success: function (res) { var code = '' code = res.code wx.request({ url: 'https://xxxx', method: 'POST', data: { appid: 'xxxxx', secret: 'xxxxx', code: code, grant_type: 'authorization_code' }, header: { "Content-Type": "application/x-www-form-urlencoded" }, success: function (res) { console.log(res) wx.requestPayment({ timeStamp: res.data["timestamp"], nonceStr: res.data["nonceStr"], package: res.data["package"], signType: 'MD5', paySign: res.data["paysign"], success: function (res) { console.log("success:"+res) }, fail:function(res){ console.log(res) } }) } }) } })
服务端:
def wxpay(request): """ 通过小程序前端 wx.login() 接口获取临时登录凭证 code 将 code 作为参数传入,调用 get_user_info() 方法获取 openid """ code = request.POST.get("code", None) data = get_user_info(code) openid = data['openid'] res_json = pay.payment(openid, "", "", "") return HttpResponse(res_json)
def get_user_info(js_code): """ 使用 临时登录凭证code 获取 session_key 和 openid 等 支付部分仅需 openid,如需其他用户信息请按微信官方开发文档自行解密 """ print("js_code:",js_code) req_params = { 'appid': settings.WECHAT['APPID'], 'secret': settings.WECHAT['APPSECRET'], 'js_code': js_code, 'grant_type': 'authorization_code', } user_info = requests.get('https://api.weixin.qq.com/sns/jscode2session', params=req_params, timeout=3, verify=False) return user_info.json()
def random_str(randomlength=32): #随机字符串生成算法 str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 random = Random() for i in range(randomlength): str+=chars[random.randint(0, length)] return str def payment(openid,goodsid,goodsnum,totalpay): #统一下单 try: openid = openid appid = 'xxxx' # 公众号id body = 'test' # 商品名 check_fee = '1' mch_id = 'xxx' # 商户号 nonceStr = random_str(32) # 随机串 notifyurl = 'https://xxxx' # 支付回调链接 out_trade_no = '099909090' # 订单号 fee = str(check_fee) # 总价 serverIP = 'xxxx' # 服务器地址 mch_key = 'xxxxx' # 支付密钥 all_pay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' # 统一下单api地址 s = "appid=" + appid + "&body=test&mch_id=" + mch_id + "&nonce_str=" + nonceStr + "¬ify_url=" + notifyurl + "&openid=" + openid + "&out_trade_no=" + out_trade_no + "&spbill_create_ip=" + serverIP + "&total_fee=" + fee + "&trade_type=JSAPI&key=" + mch_key paysign = hashlib.md5(s.encode('UTF-8')).hexdigest().upper() pay_xml = "<xml>" \ "<appid>" + appid + "</appid>" \ "<body>" + body + "</body>" \ "<mch_id>" + mch_id + "</mch_id>" \ "<nonce_str>" + nonceStr + "</nonce_str>" \ "<notify_url>" + notifyurl + "</notify_url>" \ "<openid>" + openid + "</openid>" \ "<out_trade_no>" + out_trade_no + "</out_trade_no>" \ "<spbill_create_ip>" + serverIP + "</spbill_create_ip>" \ "<total_fee>" + fee + "</total_fee>" \ "<trade_type>JSAPI</trade_type>" \ "<sign>" + paysign + "</sign></xml> " headers = {'Content-Type': 'text/xml'} # 访问支付接口 # print(pay_xml) r = requests.post(all_pay_url, data=pay_xml.encode('utf-8'), headers=headers) r.encoding = "utf-8" # print(r.text) xml_recv = ET.fromstring(r.text) wxre_sign = xml_recv.find('sign').text # 用来校验签名认证 prepay_id = xml_recv.find('prepay_id').text package = "prepay_id=" + prepay_id ctime = str(int(time.time())) stringB = "appId=" + appid + "&nonceStr=" + nonceStr + "&package=" + package + "&signType=MD5&timeStamp=" + ctime stringBSignTemp = stringB + "&key="+mch_key # 二次签名 paysign = hashlib.md5(stringBSignTemp.encode('utf-8')).hexdigest().upper() res_json = json.dumps({'rcode': 200, 'package': package, 'paysign': paysign, 'timestamp': ctime, 'nonceStr': nonceStr, 'appId': appid}) print(res_json) return res_json except Exception as err: print(str(err) + '下单异常') return json.dumps({'rcode': 400, 'msg': '下单异常'})