APP提现之微信服务号红包
来源:互联网 发布:魔法精灵软件下载 编辑:程序博客网 时间:2024/05/02 13:30
现在很多APP都有提现功能,而提现大部分都是用微信提现,微信提现有两种,一是红包,二是企业付款,在这里结合一下开发,做一些微信服务号发送红包功能的介绍。
例如当前比较火的直播APP映客的提现就是通过微信公众号的红包功能实现的。它的流程是在APP内绑定微信号,然后需要绑定的微信号关注特定的公众号,关注之后就可以在APP内或者公众号提现,公众号通过红包的形式实现提现功能。这一切的前提是要关注特定
的公众号。由于微信红包是通过公众号发送的,这个时候就需要知道绑定的微信相对于这个公众号的openid,通过关注可以获得openid。
2 服务器通过code获取用户access_token和openid,参照https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
3 通过access_token和openid获得unionid,并记录该APP用户的unionid,以方便在关注公众号的时候获取对应的openid, 参照http://mp.weixin.qq.com/wiki/1/8a5ce6257f1d3b2afb20f83e72b72ce9.html
这个公众号是微信开放平台https://open.weixin.qq.com/里面所绑定的公众号,平台里面的移动应用应该包括了你需要实现提现功能的APP
1 公众号开启开发模式,如何开启请自行搜索(开启开发模式之后,原来公众号设置的自动回复,菜单等功能全部会失效,需要开发者自己实现)
2 填写开发模式的服务器配置 参照http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html
我选择的是明文模式,配置之后,要确定这个服务器url能够正常访问。
3 验证服务器地址的有效性
我这边采用的是twisted框架用python实现的web开发,由于采用的是明文模式,验证代码只原样返回了'echostr'
4 获取微信公众号的access_token,参照https://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html,并使用redis做缓存处理,
5 依据接口文档实现业务逻辑
由于公众号的菜单功能已经失效,需要重新配置菜单,我是参照https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=自定义菜单&form=自定义菜单创建接口%20/menu/create 创建菜单,其中的access_token通过公众号的APPID和APPSECRET获得,也>可以根据http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html使用代码实现。
6 关注/取消关注事件,参照https://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html
在发生这类事件的时候,我们配置的服务器url会收到调用,参数如下
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>
'EVENT'是subscribe和unsubscribe分表表示关注和取消关注,'FromUserName'为微信用户的openid,我们可以根据公众号的access_token和这个openid获取用户的信息,参照https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html,这个里
2 由于红包需要微信用户去领取,所以APP服务器需要不断查询红包状态,查询参照https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_7&index=6
例如当前比较火的直播APP映客的提现就是通过微信公众号的红包功能实现的。它的流程是在APP内绑定微信号,然后需要绑定的微信号关注特定的公众号,关注之后就可以在APP内或者公众号提现,公众号通过红包的形式实现提现功能。这一切的前提是要关注特定
的公众号。由于微信红包是通过公众号发送的,这个时候就需要知道绑定的微信相对于这个公众号的openid,通过关注可以获得openid。
APP内部绑定微信号
1 客户端通过微信AUTH获得微信的code发送给服务器2 服务器通过code获取用户access_token和openid,参照https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
3 通过access_token和openid获得unionid,并记录该APP用户的unionid,以方便在关注公众号的时候获取对应的openid, 参照http://mp.weixin.qq.com/wiki/1/8a5ce6257f1d3b2afb20f83e72b72ce9.html
公众号配置
这个公众号是微信开放平台https://open.weixin.qq.com/里面所绑定的公众号,平台里面的移动应用应该包括了你需要实现提现功能的APP1 公众号开启开发模式,如何开启请自行搜索(开启开发模式之后,原来公众号设置的自动回复,菜单等功能全部会失效,需要开发者自己实现)
2 填写开发模式的服务器配置 参照http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html
我选择的是明文模式,配置之后,要确定这个服务器url能够正常访问。
3 验证服务器地址的有效性
我这边采用的是twisted框架用python实现的web开发,由于采用的是明文模式,验证代码只原样返回了'echostr'
4 获取微信公众号的access_token,参照https://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html,并使用redis做缓存处理,
5 依据接口文档实现业务逻辑
由于公众号的菜单功能已经失效,需要重新配置菜单,我是参照https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=自定义菜单&form=自定义菜单创建接口%20/menu/create 创建菜单,其中的access_token通过公众号的APPID和APPSECRET获得,也>可以根据http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html使用代码实现。
6 关注/取消关注事件,参照https://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html
在发生这类事件的时候,我们配置的服务器url会收到调用,参数如下
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>
'EVENT'是subscribe和unsubscribe分表表示关注和取消关注,'FromUserName'为微信用户的openid,我们可以根据公众号的access_token和这个openid获取用户的信息,参照https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html,这个里
面包含了unionid,这个unionid和通过APP内部绑定时获得unionid相同的时候就可以把APP用户和微信公众号的openid对应起来,之后我们就可以在APP申请提现,公众号发红包实现提现。
这部分的部分代码如下
class EventNotify(GreenResource): isLeaf = True def green_render_GET(self, request): return arg_named(request, 'echostr') def green_render_POST(self, request): data = request.content.read() root = ElementTree.fromstring(data) response = {child.tag: child.text for child in root.getchildren()} ret_xml = '' event_type = response.get('Event') openid = response.get('FromUserName') if event_type == 'subscribe': wx_user = WXClient.get_fuwuhao_user_info(opened) #获取用户信息 if not wx_user or wx_user.get('errcode'): logging.info(wx_user) return unionid = wx_user.get('unionid') nickname = wx_user.get('nickname') fwh = PWWeixinFuwuhao.find_or_new(openid) fwh.unionid = unionid fwh.nickname = nickname fwh.save() bind_query = WeixinBind.query(master=True, fetchone=False, unionid=unionid) #使用psql获取app用户 bind_all = [WeixinBind(**each) for each in bind_query] for bind_one in bind_all: bind_one.openid = openid bind_one.save() ret_fmt = '''<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml> ''' ret_parm = ( response.get('FromUserName'), response.get('ToUserName'), int(time.time()), config.WX_FWH_AUTO_MSG, ) ret_xml = ret_fmt % ret_parm elif event_type == 'unsubscribe': result = WeixinFuwuhao.delete(openid=openid) if not result:logging.info('fuwuhao unsubscribe is not exist %s' % (openid, )) elif response.get('MsgId'): ret_fmt = '''<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml> ''' ret_parm = ( response.get('FromUserName'), response.get('ToUserName'), int(time.time()), config.WX_FWH_AUTO_MSG_2, ) ret_xml = ret_fmt % ret_parm return ret_xml
公众号发送红包
1 发送红包,微信红包针对所有用户、单个用户都有发送频率的限制,金额也有限制,如果提现金额大于红包最大金额,需要分批发送。参照https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_52 由于红包需要微信用户去领取,所以APP服务器需要不断查询红包状态,查询参照https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_7&index=6
每个红包是 SENDING:发放中 SENT:已发放待领取 FAILED:发放失败 RECEIVED:已领取 REFUND:已退款 中的任何一种状态,只有 为FAILED RECEIVED REFUND状态的时候表示这个红包的生命周期已经结束
部分代码如下
class WeixinWithdrawOrder(object): def __init__(self, withhdraw_id, openid, mch_billno, total_amount): self.wid = withhdraw_id self.pw_tid = 0 self.nonce_str = hashlib.md5('%s-%s' % (self.wid, time.time())).hexdigest() self.mch_id = config.WX_FWH_MCH_ID self.mch_billno = mch_billno self.wxappid = config.WX_FWH_APPID self.send_name = config.WX_WITHDRAW_SEND_NAME self.re_openid = openid self.total_amount = 100 if config.ENV_TEST else total_amount self.total_num = 1 self.act_name = config.WX_WITHDRAW_ACT_NAME self.wishing = config.WX_WITHDRAW_WISHING self.client_ip = config.WX_PAY_IP_ADDR self.remark = config.WX_WITHDRAW_REMARK @classmethod def sign(cls, data): weixin_params = [] for key, value in data.iteritems(): if key not in ('wid', 'sign', 'pw_tid', ): weixin_params.append([str(key), str(value)]) weixin_params.sort(key=lambda x:x[0]) sign_src = '%s&key=%s' % ('&'.join(['%s=%s'%(x[0], x[1]) for x in weixin_params]), config.WX_FWH_MCH_KEY) logging.info(sign_src) return hashlib.md5(sign_src).hexdigest().upper() def order(self): return '''<xml> <nonce_str>%s</nonce_str> <sign>%s</sign> <mch_billno>%s</mch_billno> <mch_id>%s</mch_id> <wxappid>%s</wxappid> <send_name>%s</send_name> <re_openid>%s</re_openid> <total_amount>%s</total_amount> <total_num>%s</total_num> <wishing>%s</wishing> <act_name>%s</act_name> <client_ip>%s</client_ip> <remark>%s</remark></xml>''' % ( self.nonce_str, WeixinWithdrawOrder.sign(self.__dict__), self.mch_billno, self.mch_id, self.wxappid, self.send_name, self.re_openid.encode('utf8'), self.total_amount, self.total_num, self.wishing, self.act_name, self.client_ip, self.remark, ) def run_withdraw(self): try: order = self.order() logging.info(order) url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack' cert = ('data/weixin/apiclient_cert.pem', 'data/weixin/apiclient_key.pem') #微信商户号的key,通过商户平台下载 data = requests.post(url, data=order, cert=cert).text #使用第三方库request root = ElementTree.fromstring(data) response = {child.tag : child.text for child in root.getchildren()} logging.info(response) if response.get('return_code') == 'SUCCESS': if response.get('result_code') == 'SUCCESS': return True, response.get('mch_billno'), response.get('err_code'), response.get('return_msg') else: logging.error(data) return False, self.mch_billno, response.get('err_code'), response.get('return_msg') else: logging.error(data) return False, self.mch_billno, response.get('err_code'), response.get('return_msg') except: traceback.print_exc() return False, self.mch_billno, 'url not connect', 'url not connect'
0 0
- APP提现之微信服务号红包
- C# .net MVC 微信红包(服务号发送红包)
- C# .net MVC 微信红包(服务号发送红包)
- 微信开发之现金红包
- APP提现之微信商户号企业付款
- 利用辅助服务AccessibilityService实现微信自动抢红包
- 微信开发之----封装微信红包类
- 微信公众号开发---红包模块
- 微信公众号 调用红包接口
- 微信公众号下发红包功能
- 微信公众号开发----现金红包
- 微信公众号发送红包
- 接口发放微信企业号红包
- 接口发放微信企业号红包
- 微信红包
- 微信红包算法
- 微信现金红包
- 微信红包算法
- 进程等待&程序替换
- .net页面缓存
- 线段树-点修改区间查询--hdu1166敌兵布阵
- 用Python 学习数据结构与算法 二、插入排序
- Max-out network--p norm
- APP提现之微信服务号红包
- **安卓事件分发机制学习**
- iOS中怎么继承Xib
- zzulioj-1905-小火山的跳子游戏【GCD】
- 线段树-点修改--点查询--最值查询 Hdu 1754I Hate It
- sql server中,N''的含义
- 杭电oj--1213 How Many Tables
- APP分享文件给微信好友
- 303.[LeetCode]Range Sum Query