$Django 支付宝支付,微信服务号推送消息 (测试需要把应用程序部署到服务器上)...
一 支付宝支付
大概
支付宝支付正式环境:需要用营业执照去申请商户号,appid测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info 支付宝提供接口:给商户使用,收钱-Java,php,C#的demo,没有python的demo(事例)-git有人封装了-需要安装模块:pip3 install pycryptodome-应用私钥---自己保存,一定不能丢-应用公钥---给别人用-支付宝公钥---支付宝用的-生成公钥私钥:https://docs.open.alipay.com/291/105971 -把应用公钥配置在支付宝上:应用公钥,配置完成以后,支付宝自动生成一个支付宝公钥-在程序中:配置应用私钥,支付宝公钥-如果支付成功,支付宝会回调,但是如果你的服务器挂掉了怎么办?-支付宝24小时以内不定时再给你发,你修改掉订单状态即可-支付成功,支付宝会有一个get回调,一个post回调:修改订单状态
沙箱测试流程(详情)
1.输入支付金额:在我们的网站往支付宝的网关https://openapi.alipaydev.com/gateway.do后面拼?账单(商品名,价格,我数据库生成的订单号等),回调的url等数据 
2.扫码支付:点击去支付来到了拼好的支付宝url 显示支付宝页面

3.支付完成:

4.回调之前拼接的url:支付宝向这个url 发起get请求:GET取数据【显示】支付成功失败和post请求:body(bytes格式)内取数据:状态/我数据库的订单号/支付宝的订单号等

代码(详情)
1.目录

2.keys:应用私钥,支付宝公钥
alipay_public_2048.txt -----BEGIN PUBLIC KEY----- # 加上这行 支付宝的公钥 -----END PUBLIC KEY----- # 同上 app_private_2048.txt -----BEGIN PUBLIC KEY----- #同上 应用的私钥 -----END PUBLIC KEY----- # 同上
3.pay.py:这是从git上找到的支付宝支付接口(PC端支付接口)
from datetime import datetime from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from urllib.parse import quote_plus from base64 import decodebytes, encodebytes import jsonclass AliPay(object):"""支付宝支付接口(PC端支付接口)"""def __init__(self, appid, app_notify_url, app_private_key_path,alipay_public_key_path, return_url, debug=False):self.appid = appidself.app_notify_url = app_notify_urlself.app_private_key_path = app_private_key_pathself.app_private_key = Noneself.return_url = return_urlwith open(self.app_private_key_path) as fp:self.app_private_key = RSA.importKey(fp.read())self.alipay_public_key_path = alipay_public_key_pathwith open(self.alipay_public_key_path) as fp:self.alipay_public_key = RSA.importKey(fp.read())if debug is True:self.__gateway = "https://openapi.alipaydev.com/gateway.do"else:self.__gateway = "https://openapi.alipay.com/gateway.do"def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):biz_content = {"subject": subject,"out_trade_no": out_trade_no,"total_amount": total_amount,"product_code": "FAST_INSTANT_TRADE_PAY",# "qr_pay_mode":4 }biz_content.update(kwargs)data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)return self.sign_data(data)def build_body(self, method, biz_content, return_url=None):data = {"app_id": self.appid,"method": method,"charset": "utf-8","sign_type": "RSA2","timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"version": "1.0","biz_content": biz_content}if return_url is not None:data["notify_url"] = self.app_notify_urldata["return_url"] = self.return_urlreturn datadef sign_data(self, data):data.pop("sign", None)# 排序后的字符串unsigned_items = self.ordered_data(data)unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)sign = self.sign(unsigned_string.encode("utf-8"))# ordered_items = self.ordered_data(data)quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)# 获得最终的订单信息字符串signed_string = quoted_string + "&sign=" + quote_plus(sign)return signed_stringdef ordered_data(self, data):complex_keys = []for key, value in data.items():if isinstance(value, dict):complex_keys.append(key)# 将字典类型的数据dump出来for key in complex_keys:data[key] = json.dumps(data[key], separators=(',', ':'))return sorted([(k, v) for k, v in data.items()])def sign(self, unsigned_string):# 开始计算签名key = self.app_private_keysigner = PKCS1_v1_5.new(key)signature = signer.sign(SHA256.new(unsigned_string))# base64 编码,转换为unicode表示并移除回车sign = encodebytes(signature).decode("utf8").replace("\n", "")return signdef _verify(self, raw_content, signature):# 开始计算签名key = self.alipay_public_keysigner = PKCS1_v1_5.new(key)digest = SHA256.new()digest.update(raw_content.encode("utf8"))if signer.verify(digest, decodebytes(signature.encode("utf8"))):return Truereturn Falsedef verify(self, data, signature):if "sign_type" in data:sign_type = data.pop("sign_type")# 排序后的字符串unsigned_items = self.ordered_data(data)message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)return self._verify(message, signature)支付宝接口
4.路由
from django.contrib import adminfrom django.conf.urls import url from app01 import viewsurlpatterns = [url('admin/', admin.site.urls),url(r'^page1/', views.page1),url(r'^page2/', views.page2), ]
5.views
from django.shortcuts import render, redirect, HttpResponse from utils.pay import AliPay import json import time def ali():# 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=infoapp_id = "2016092000554611"# 支付宝收到用户的支付,会向商户发两个请求,一个get请求,一个post请求# POST请求,用于最后的检测notify_url = "http://42.56.89.12:80/page2/"# GET请求,用于页面的跳转展示return_url = "http://42.56.89.12:80/page2/"#应用私钥merchant_private_key_path = "keys/app_private_2048.txt"#支付宝公钥alipay_public_key_path = "keys/alipay_public_2048.txt"# 生成一个AliPay的对象alipay = AliPay(appid=app_id,app_notify_url=notify_url,return_url=return_url,app_private_key_path=merchant_private_key_path,alipay_public_key_path=alipay_public_key_path, # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥debug=True, # 默认False, )return alipaydef page1(request):if request.method == "GET":return render(request, 'page1.html')else:money = float(request.POST.get('money'))# 生成一个对象alipay = ali()# 生成支付的url# 对象调用direct_payquery_params = alipay.direct_pay(subject="充气娃娃", # 商品简单描述out_trade_no="x2" + str(time.time()), # 商户订单号total_amount=money, # 交易金额(单位: 元 保留俩位小数) )pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)print(pay_url)# 朝这个地址发get请求return redirect(pay_url)def page2(request):alipay = ali()if request.method == "POST":# 检测是否支付成功# 去请求体中获取所有返回的数据:状态/订单号from urllib.parse import parse_qsbody_str = request.body.decode('utf-8')print(body_str)post_data = parse_qs(body_str)print('支付宝给我的数据:::---------',post_data)post_dict = {}for k, v in post_data.items():post_dict[k] = v[0]print('转完之后的字典',post_dict)sign = post_dict.pop('sign', None)status = alipay.verify(post_dict, sign)print('POST验证', status)return HttpResponse('POST返回')else:params = request.GET.dict()sign = params.pop('sign', None)status = alipay.verify(params, sign)print('GET验证', status)return HttpResponse('支付成功')
6.template
"en"> "UTF-8">Title "stylesheet" href="dist/css/bootstrap.css">
二 微信服务号推送消息
大概
用什么推送-邮件-微信推送-短信推送微信推送-公众号(群聊)-认证的公众号:需要营业执照,需要交钱,可以发多篇文章-未认证的公众号:一天只能发一篇文章-服务号(微信推送)(私聊)-需要申请,需要认证-可以主动给单个用户推送消息-能给推送的人,必须关注我的服务号-沙箱环境:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
-企业号 -企业里用的: -你们所见的二维码:其实就是一个url地址 -咱们在前端通过url(https://open.weixin.qq.com/connect/oauth2.....)生成一个二维码
-注意*****修改:网页授权获取用户基本信息
代码(详情)
1.目录

2.路由
from django.conf.urls import url from django.contrib import admin from app01 import viewsurlpatterns = [url(r'^admin/', admin.site.urls),url(r'^login/$', views.login),url(r'^index/$', views.index),url(r'^bind/$', views.bind),url(r'^bind_qcode/$', views.bind_qcode),url(r'^callback/$', views.callback),url(r'^sendmsg/$', views.sendmsg), ]
3.settings.py
# ############# 微信 ############## WECHAT_CONFIG = {'app_id': 'wx3e1f0883236623f9','appsecret': '508ec4590702c76e6863be6df01ad95a','redirect_uri': 'http://42.56.89.12/callback/', }
4.models.py
import hashlib from django.db import modelsclass UserInfo(models.Model):username = models.CharField("用户名", max_length=64, unique=True)password = models.CharField("密码", max_length=64)uid = models.CharField(verbose_name='个人唯一ID',max_length=64, unique=True)wx_id = models.CharField(verbose_name="微信ID", max_length=128, blank=True, null=True, db_index=True)def save(self, *args, **kwargs):# 创建用户时,为用户自动生成个人唯一IDif not self.pk:m = hashlib.md5()m.update(self.username.encode(encoding="utf-8"))self.uid = m.hexdigest()super(UserInfo, self).save(*args, **kwargs)
5.views.py
import json import functools import requests from django.conf import settings from django.shortcuts import render, redirect, HttpResponse from django.http import JsonResponse from app01 import models # 沙箱环境地质:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login def index(request):obj = models.UserInfo.objects.get(id=1)return render(request,'index.html',{'obj':obj})def auth(func):def inner(request, *args, **kwargs):user_info = request.session.get('user_info')if not user_info:return redirect('/login/')return func(request, *args, **kwargs)return innerdef login(request):"""用户登录:param request: :return: """# models.UserInfo.objects.create(username='luffy',password=123)if request.method == "POST":user = request.POST.get('user')pwd = request.POST.get('pwd')obj = models.UserInfo.objects.filter(username=user, password=pwd).first()if obj:request.session['user_info'] = {'id': obj.id, 'name': obj.username, 'uid': obj.uid}return redirect('/bind/')else:return render(request, 'login.html')@auth def bind(request):"""用户登录后,关注公众号,并绑定个人微信(用于以后消息推送):param request: :return: """return render(request, 'bind.html')@auth def bind_qcode(request):"""生成二维码:param request: :return: """ret = {'code': 1000}try:access_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}&redirect_uri={redirect_uri}&response_type=code&scope=snsapi_userinfo&state={state}#wechat_redirect"access_url = access_url.format(# 商户的appidappid=settings.WECHAT_CONFIG["app_id"], # 'wx6edde7a6a97e4fcd',# 回调地址redirect_uri=settings.WECHAT_CONFIG["redirect_uri"],# 当前登录用户的唯一idstate=request.session['user_info']['uid'] # 为当前用户生成MD5值 )ret['data'] = access_urlexcept Exception as e:ret['code'] = 1001ret['msg'] = str(e)return JsonResponse(ret)def callback(request):"""用户在手机微信上扫码后,微信自动调用该方法。用于获取扫码用户的唯一ID,以后用于给他推送消息。:param request: :return: """code = request.GET.get("code")# 用户md5值,用户唯一idstate = request.GET.get("state")# 获取该用户openId(用户唯一,用于给用户发送消息)# request模块朝https://api.weixin.qq.com/sns/oauth2/access_token地址发get请求res = requests.get(url="https://api.weixin.qq.com/sns/oauth2/access_token",params={"appid": 'wx3e1f0883236623f9',"secret": '508ec4590702c76e6863be6df01ad95a',"code": code,"grant_type": 'authorization_code',}).json()# res.data 是json格式# res=json.loads(res.data)# res是一个字典# 获取的到openid表示用户授权成功openid = res.get("openid")if openid:models.UserInfo.objects.filter(uid=state).update(wx_id=openid)response = "视图授权成功 %s
" % openidelse:response = "用户扫码之后,手机上的提示
"return HttpResponse(response)def sendmsg(request):def get_access_token():"""获取微信全局接口的凭证(默认有效期俩个小时)如果不每天请求次数过多, 通过设置缓存即可"""result = requests.get(url="https://api.weixin.qq.com/cgi-bin/token",params={"grant_type": "client_credential","appid": settings.WECHAT_CONFIG['app_id'],"secret": settings.WECHAT_CONFIG['appsecret'],}).json()if result.get("access_token"):access_token = result.get('access_token')else:access_token = Nonereturn access_tokenaccess_token = get_access_token()openid = models.UserInfo.objects.get(id=1).wx_iddef send_custom_msg():body = {"touser": openid,"msgtype": "text","text": {"content": 'lqz大帅哥'}}response = requests.post(url="https://api.weixin.qq.com/cgi-bin/message/custom/send",# 放到路径?后面的东西params={'access_token': access_token},# 这是post请求body体中的内容data=bytes(json.dumps(body, ensure_ascii=False), encoding='utf-8'))# 这里可根据回执code进行判定是否发送成功(也可以根据code根据错误信息)result = response.json()return resultdef send_template_msg():"""发送模版消息"""res = requests.post(url="https://api.weixin.qq.com/cgi-bin/message/template/send",params={'access_token': access_token},json={"touser": openid,"template_id": 'IaSe9s0rukUfKy4ZCbP4p7Hqbgp1L4hG6_EGobO2gMg',"data": {"first": {"value": "lqz","color": "#173177"},"keyword1": {"value": "大帅哥","color": "#173177"},}})result = res.json()return resultresult = send_custom_msg()if result.get('errcode') == 0:return HttpResponse('发送成功')return HttpResponse('发送失败')
6.template.py
"en"> "UTF-8">login.htmlTitle
{% load staticfiles %}
"en">
"UTF-8">Title
"width: 600px;margin: 0 auto">请关注路飞学城服务号,并绑定个人用户(用于以后的消息提醒)
第一步:关注路飞学城微信服务号
"height: 100px;width: 100px" src="{% static "img/luffy.jpeg" %}">"button" value="下一步【获取绑定二维码】" οnclick="getBindUserQcode()">第二步:绑定个人账户
"qrcode" style="width: 250px;height: 250px;background-color: white;margin: 100px auto;">
{#qrcode 可以生成二维码 #}
bind.html(重点)
"zh-CN"> "UTF-8">index.htmlTitle "viewport" content="width=device-width, initial-scale=1">{{ obj.username }} -> {{ obj.wx_id }}
沙箱测试流程(详情)
1.先去微信 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login申请服务号:拿到appid,appsecret,服务号二维码


2.为了给微信用户推送信息(我们的服务器数据库要存上用户的微信号,如上图):先要关注服务号,然后诱导用户向我们拼好的一个微信url连接发请求
ret = {'code': 1000}try:access_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}&redirect_uri={redirect_uri}&response_type=code&scope=snsapi_userinfo&state={state}#wechat_redirect"access_url = access_url.format(# 商户的appidappid=settings.WECHAT_CONFIG["app_id"], # 'wx6edde7a6a97e4fcd',# 回调地址redirect_uri=settings.WECHAT_CONFIG["redirect_uri"],# 当前登录用户的唯一idstate=request.session['user_info']['uid'] # 为当前用户生成MD5值
)ret['data'] = access_urlexcept Exception as e:ret['code'] = 1001ret['msg'] = str(e) 拼好的链接(回调地址,我们服务器用户信息,appid,appsecret,)
{#qrcode 可以生成二维码 #}
url生成二维码,让用户扫 
3.回调地址:微信根据回调地址再向我们服务器发请求,获得数据的同时我们服务器又向微信某个地址发送了一个request.get(爬虫请求)直接拿到了用户的微信号,更新到我们的数据库
#回调地址的路由url(r'^callback/$', views.callback) def callback(request):"""用户在手机微信上扫码后,微信自动调用该方法。用于获取扫码用户的唯一ID,以后用于给他推送消息。:param request: :return: """code = request.GET.get("code")# 用户md5值,用户唯一idstate = request.GET.get("state")# 获取该用户openId(用户唯一,用于给用户发送消息)# request模块朝https://api.weixin.qq.com/sns/oauth2/access_token地址发get请求res = requests.get(url="https://api.weixin.qq.com/sns/oauth2/access_token",params={"appid": 'wx3e1f0883236623f9',"secret": '508ec4590702c76e6863be6df01ad95a',"code": code,"grant_type": 'authorization_code',}).json()# res.data 是json格式# res=json.loads(res.data)# res是一个字典# 获取的到openid表示用户授权成功openid = res.get("openid")if openid:models.UserInfo.objects.filter(uid=state).update(wx_id=openid)response = "授权成功 %s
" % openidelse:response = "用户扫码之后,手机上的提示
"return HttpResponse(response)
4.最终:用户扫码后会得到回调地址的返回信息,例如 '授权成功'
5.我们定义了一个sendmsg(request)视图:1爬取当前用户的token,2服务器拿着token、用户微信号向微信发消息。这样用户就收到了服务号私发的信息
def sendmsg(request):def get_access_token():"""获取微信全局接口的凭证(默认有效期俩个小时)如果不每天请求次数过多, 通过设置缓存即可"""result = requests.get(url="https://api.weixin.qq.com/cgi-bin/token",params={"grant_type": "client_credential","appid": settings.WECHAT_CONFIG['app_id'],"secret": settings.WECHAT_CONFIG['appsecret'],}).json()if result.get("access_token"):access_token = result.get('access_token')else:access_token = Nonereturn access_tokenaccess_token = get_access_token()openid = models.UserInfo.objects.get(id=1).wx_iddef send_custom_msg():body = {"touser": openid,"msgtype": "text","text": {"content": 'lqz大帅哥'}}response = requests.post(url="https://api.weixin.qq.com/cgi-bin/message/custom/send",# 放到路径?后面的东西params={'access_token': access_token},# 这是post请求body体中的内容data=bytes(json.dumps(body, ensure_ascii=False), encoding='utf-8'))# 这里可根据回执code进行判定是否发送成功(也可以根据code根据错误信息)result = response.json()return resultdef send_template_msg():"""发送模版消息"""res = requests.post(url="https://api.weixin.qq.com/cgi-bin/message/template/send",params={'access_token': access_token},json={"touser": openid,"template_id": 'IaSe9s0rukUfKy4ZCbP4p7Hqbgp1L4hG6_EGobO2gMg',"data": {"first": {"value": "lqz","color": "#173177"},"keyword1": {"value": "大帅哥","color": "#173177"},}})result = res.json()return resultresult = send_custom_msg()if result.get('errcode') == 0:return HttpResponse('发送成功')return HttpResponse('发送失败')服务号向粉丝发消息
转载于:https://www.cnblogs.com/3sss-ss-s/p/10185255.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
