需求:

微信打开商品列表页面-> 点击商品后直接显示付款页面-> 点击付款调用微信支付

说明

微信支付需要你申请了公众号(appid, key - 用于签名), 商户号(mch_id, AppSecret - 用于获取openid, 获取code)

调起微信支付的页面需要配置授权, 如你的页面是http://www.shazuihuo.com/goods/index.html. 那么你需要配置为: http://www.shazuihuo.com/goods/ 即可, 这个是在公众号中配置



签名算法和校验工具

  1. 签名校验通过时还是提示签名错误, 可能时候商户号KEY配置的问题了, 重置一下KEY, 你可以继续使用原来的KEY来重置
  2. 公众号变更时记得修改后台和前台代码中的APPID

需要的ID和KEY

# 微信配置基础数据
WPC = {
'APPID': 'wx53c1xxxxad626eb8',
'APPSECRET': 'fdd177a7xxxxxxxxxxxxx856eeeb187c',
'MCHID': '14222000000',
'KEY': 'd7810713e1exxxxxxxxxxadc9617d0a6',
'GOODDESC': '商户号中的公司简称或全称-无要求的商品名字',
'NOTIFY_URL': 'https://www.xxxx.com/service/applesson/wechatordernotice',
}

流程简介

  1. 网页内调起微信支付需要一个微信统一下单生成的订单号(prepay_id)
  2. 调用微信的统一下单接口需要一个用户在商户下的唯一标示(openid)
  3. 获取openid需要code参数加上AppID和AppSecret等,通过API换取access_token(openid)
  4. 其中code又需要通过页面跳转来获取, 需要appid和重定向url(可以带有你自己的参数, 会原样返回)

    那么开发思路便是一步步回朔了.

1. 获取code

用户点击按钮跳转到微信授权页, 微信处理完后重定向到redirect_uri, 并给我们加上code=xxx的参数, 这个code就是我们需要的

    $('#buy').click(function() {
var param = {
appid: 'wx53c1xxxxad626eb8',
redirect_uri: 'https://www.xxxxx.com/wcpay/pay.html',
response_type: 'code',
scope: 'snsapi_base',
state: '1'
}
window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?' + $.param(param);
})

2. 获取openid

这个在后台完成, WPC中配置了你的APPSECRET, 这个不能泄露, 接口调用成功会拿到一个openid, 这里都不会有什么问题

    @classmethod
def getOpenID(cls, kwargs):
param = {
'code': kwargs['code'],
'appid': WPC['APPID'],
'secret': WPC['APPSECRET'],
'grant_type': 'authorization_code',
} # 通过code获取access_token
openIdUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token'
resp = requests.get(openIdUrl, params=param)
# {openid, accss_token, refresh_token, openid, scope, expires_in}
# openId = json.loads(resp.text)['openid']
return resp.text

3. 微信统一下单

统一下单 时参数传递需要签名(微信用我们设定的密匙对参数进行MD5加密, 通过双方的签名判断请求是否被篡改)

签名算法

@classmethod
def getSign(cls, kwargs): # 计算签名
keys, paras = sorted(kwargs), []
paras = ['{}={}'.format(key, kwargs[key]) for key in keys if key != 'appkey'] # and kwargs[key] != '']
stringA = '&'.join(paras) stringSignTemp = stringA + '&key=' + WPC['KEY']
sign = MD5(stringSignTemp).upper() return sign

MD5函数

import hashlib

# 获取MD5
def MD5(str):
md5 = hashlib.md5()
md5.update(str.encode('utf-8'))
return md5.hexdigest()

参数转xml

@classmethod
def getxml(cls, kwargs): kwargs['sign'] = Utility.getSign(kwargs) # 生成xml
xml = ''
for key, value in kwargs.items():
xml += '<{0}>{1}</{0}>'.format(key, value)
xml = '<xml>{0}</xml>'.format(xml) # print(xml)
return xml

统一下单代码

code = self.POST.get('code')
openidresp = Utility.getOpenID({'code': code})
openid = json.loads(openidresp).get('openid') UnifieOrderRequest = {
'appid': 'wx53c1xxxxad626eb8', # 公众账号ID
'body': '公司名称-商品', # 商品描述
'mch_id': '1397xxxxxx8', # 商户号:深圳市泽慧文化传播有限公司
'nonce_str': '', # 随机字符串
'notify_url': 'https://service.xxxx.com/service/applesson/wechatordernotice', # 微信支付结果异步通知地址
'openid': '', # trade_type为JSAPI时,openid为必填参数!此参数为微信用户在商户对应appid下的唯一标识, 统一支付接口中,缺少必填参数openid!
'out_trade_no': '', # 商户订单号
'spbill_create_ip': '', # 终端IP
'total_fee': '', # 标价金额
'trade_type': 'JSAPI', # 交易类型
}
UnifieOrderRequest['nonce_str'] = Utility.getnoncestr()
UnifieOrderRequest['openid'] = openid
UnifieOrderRequest['out_trade_no'] = UnifieOrderRequest['mch_id'] + str(order.id) # 内部订单号码
UnifieOrderRequest['spbill_create_ip'] = self.request.remote_ip
UnifieOrderRequest['total_fee'] = int(lesson.price * 100)
# 签名并生成xml
xml = Utility.getxml(UnifieOrderRequest) resp = requests.post("https://api.mch.weixin.qq.com/pay/unifiedorder", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
prepay_id = '' if xmlresp['xml']['return_code'] == 'SUCCESS':
if xmlresp['xml']['result_code'] == 'SUCCESS':
prepay_id = xmlresp['xml']['prepay_id']
timestamp = str(int(time.time()))
data = {
"appId": xmlresp['xml']['appid'],
"nonceStr": Utility.getnoncestr(),
"package": "prepay_id=" + xmlresp['xml']['prepay_id'],
"signType": "MD5",
"timeStamp": timestamp
}
data['paySign'] = Utility.getSign(data)
data['orderid'] = order.id # 付款后操作的订单
# 签名后返回给前端做支付参数
return JsonResponse(self, '000', data=data)
else:
msg = xmlresp['xml']['err_code_des']
return JsonResponse(self, '002', msg=msg)
else:
msg = xmlresp['xml']['return_msg']
return JsonResponse(self, '002', msg=msg)

统一下单成功返回后直接调用微信支付, 显示支付界面, 其中的paySign是我们自己的签名

try {
// statements
// 微信统一订单, 返回预支付信息
var code = query('code'),
origin = query('groupid');
// alert(code); $.post({
url: orderurl,
data: {
origin: origin,
mobile: phone,
code: code
}
}).then(function(resp) {
if (resp.code && resp.code == "000") {
// 后台返回订单信息
var wepaydata = {
appId: resp.data.appId,
nonceStr: resp.data.nonceStr,
package: resp.data.package,
paySign: resp.data.paySign,
signType: "MD5",
timeStamp: resp.data.timeStamp
};
var orderid = resp.data.orderid || 0; window.jsApiCall = function() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
wepaydata,
function(res) {
WeixinJSBridge.log(res.err_msg);
// alert(res.err_code + res.err_desc + res.err_msg);
// alert(res.err_msg)
if (res.err_msg == 'get_brand_wcpay_request:ok') {
$.get(orderurl, { orderid: orderid }, function(resp) {
if (resp.code == '000') {
window.location.href = window.location.href.replace('pay.html', 'success.html');
} else {
alert(resp.msg);
// 一个code只能请求一次, 重新进入index
if (resp.code == '002') {
window.location.href = window.location.href.replace('pay.html', 'index.html');
}
}
});
} else {
// 其他支付异常微信有显示消息
// alert(res.err_msg);
}
}
);
} window.callpay = function() {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
} else {
jsApiCall();
} } // 发起支付
window.callpay(); } else {
alert(resp.msg);
// alert(JSON.stringify(resp) + resp.msg);
}
}, function(resp) {
alert(resp)
alert(JSON.stringify(resp)) // alert('请求失败, 请重试');
});
} catch (e) {
// statements
alert(e)
}

4. 订单查询

订单查询 是为了确认我们的支付是成功的

# 查询微信付款情况
orderid = self.GET.get('orderid')
orderquery = {
'appid': WPC['APPID'],
'mch_id': WPC['MCHID'],
'nonce_str': Utility.getnoncestr(),
'out_trade_no': WPC['MCHID'] + orderid
}
xml = Utility.getxml(orderquery)
print(xml) resp = requests.post("https://api.mch.weixin.qq.com/pay/orderquery", data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})
msg = resp.text.encode('ISO-8859-1').decode('utf-8')
xmlresp = xmltodict.parse(msg)
print(xmlresp) orderPaid = 0
if xmlresp['xml']['return_code'] == 'SUCCESS':
if xmlresp['xml']['result_code'] == 'SUCCESS':
if xmlresp['xml']['trade_state'] == 'SUCCESS':
orderPaid = 1
else:
msg = xmlresp['xml']['trade_state_desc']
return JsonResponse(self, '001', msg=smg)
else:
msg = xmlresp['xml']['err_code_des']
return JsonResponse(self, '001', msg=msg)
else:
msg = xmlresp['xml']['return_msg']
return JsonResponse(self, '001', msg=msg)

官方Demo

SDK与DEMO下载, 用python就需要自己码代码, 当时看的是PHP的

微信支付 python版的更多相关文章

  1. 微信支付java版V3验证数据合法性

    [TOC] 1. 微信支付java版V3验证数据合法性 概要:使用微信支付接口时,微信会返回或回调给商户XML数据,开发者需要验证微信返回的数据是否合法. 特别提醒:商户系统对于支付结果通知的内容一定 ...

  2. Zabbix 微信报警Python版(带监控项波动图片)

    #!/usr/bin/python # -*- coding: UTF- -*- #Function: 微信报警python版(带波动图) #Environment: python import ur ...

  3. 微信支付.NET版开发总结(JS API),好多坑,适当精简

    前2天,做一个手机网页的微信支付的项目,费了好些周折,记录一下.接下来,按照开发步骤,细数一下,我遇到的那些坑. [坑1]官方邮件中下载的demo只有PHP版本,其他版本没有给链接.可能让人误以为只有 ...

  4. 微信支付.NET版开发总结(JS API),好多坑,适当精简。

    前2天,做一个手机网页的微信支付的项目,费了好些周折,记录一下.接下来,按照开发步骤,细数一下,我遇到的那些坑. [坑1]官方邮件中下载的demo只有PHP版本,其他版本没有给链接.可能让人误以为只有 ...

  5. Android微信支付V3版

    由于公司需求做微信APP支付,在集成过程中也遇到各种问题,比如说签名错误,body编码必须为UTF-8.APP端无法调用支付页面直接到支付结果页面.结果为null,code=-1等等: 1.签名错误问 ...

  6. jsapi微信支付v3版

    请看清楚你的微信支付是v2还是v3.在这里整理的是v3的,v2的同学请忽略! 前期准备须要用的是商户证书,用的是p12的.设置api密钥(在微信商户端中设置),还须要在微信公众号中设置jsapi授权文 ...

  7. 微信支付 V3版

    本人小菜鸟一仅仅.为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,server)等一系列的知识,小菜鸟创建了一个群.希望光临本博客的人能够进来交流. 寻 ...

  8. zabbix之微信告警(python版):微信个人报警,微信企业号告警脚本

    微信个人告警脚本 微信个人告警:使用个人微信,发送到微信群组,微信好友 两个脚本执行: 1)能连接网络2)先执行server.py,扫描登录微信,登录之后没有报错,打开新终端查看端口是否起来了3)在z ...

  9. 到处都是坑的微信支付V3

    业务需要一个在微信上能付款的功能,于是乎想到了最普遍的支付宝,坑爹的是T与A是水火不容啊,默默的还是接微信支付吧,没想到从此掉进了连环坑…… 网上写微信支付接口的还是很多,PHP官方有(鄙视源码作者, ...

随机推荐

  1. P2661 信息传递 二分图的最小环

    题目描述 有 nn 个同学(编号为 11 到 nn )正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为 ii 的同学的信息传递对象是编号为 T_iTi​ 的同学. 游戏开 ...

  2. Xamarin Essentials教程磁力计Magnetometer

    Xamarin Essentials教程磁力计Magnetometer   磁力计也叫地磁.磁感器,可用于测试磁场强度和方向.在手持设备中,通过磁力计可以计算设备的左右.前后倾斜角度,广泛应用于手机各 ...

  3. 杭电2000----ASCII码排序

    #include<stdio.h> int main() { ]; int i,j,t; while(gets(a)!=NULL) { ; i<; ++i) ; j<-i; + ...

  4. Java基础(十三) 文件高级技术

    文件高级技术 一.常见文件类型处理 一)属性文件 属性文件很简单,一行表示一个属性,属性就是键值对,键和值用(=)或者(:)分隔. #ready to work name = tang age = p ...

  5. Kotlin基础(三)类、对象和接口

    类.对象和接口 一.定义类的继承结构 一)Kotlin中的接口 Kotlin的接口与Java8中相似,它们可以包含抽象方法的定义以及非抽象方法的实现,但它们不能包含任何状态. interface Cl ...

  6. 生成树的计数 Matrix-Tree(矩阵树)定理

    信息学竞赛中,有关生成树的最优化问题如最小生成树等是我们经常遇到的,而对生成树的计数及其相关问题则少有涉及.事实上,生成树的计数是十分有意义的,在许多方面都有着广泛的应用.本文从一道信息学竞赛中出现的 ...

  7. IDEA 配置datasource,提升编码效率,让你在 Mapper.xml 中编写sql可以飞起来~

    IDEA 2018 创建springboot工程后,如果你打开一个.sql文件,或者一个mybatis的mapper.xml文件,会提示: No data source are configured ...

  8. MySql 5.7.20版本免安装版配置过程

    下载地址为: https://dev.mysql.com/downloads/mysql/ 最下面根据自己的操作系统选择合适的型号 下载完以后解压缩到自定义的路径.这里注意的是路径中不要存在中文. 解 ...

  9. C++程序设计方法4:模板特化

    模板参数的具体化/特殊化 有时,有些类型不适用,则需要对模板进行特殊化处理,这称为“模板特化” 对函数模板,如果有多个模板参数,则特化时必须提供所有参数的特例类型,不能部分特化: 如: char *s ...

  10. C++程序设计方法3:禁止自动类型转换

    禁止自动类型转换 explicit #include <iostream> using namespace std; class Src;//前置类型声明,因为在Dst中要用到Src的类 ...