支付宝支付和微信消息推送

支付宝支付

  如果想在网站上,通过扫码支付宝收钱,你必须到支付宝网站https://openhome.alipay.com/platform/home.htm申请账号,但是正式的,需要你提供营业执照,现在没有,也不要紧,支付宝还提供一个沙箱的测试环境

  服务商注册:业务只是网站上收个钱,注册一个支付系统服务商就可以了

  注册完成后,进入我的蚂蚁金服开方平台首页,进行应用创建就可以了(这是正式的,需要营业执照)

  程序开发使用时,你只需要按照支付宝提供的接口规则和加密方法进行数据传递就可以了

  现在没有营业执照,怎么玩,搞个沙箱环境玩玩

  开发者中心-->开发服务-->研发服务,点进去,支付宝会提供一些数据给我们进行测试,其中APPID,支付宝网关(带dev就是测试地址)

  并且支付宝,提供一个测试的支付宝app,需要测试扫码支付,就要下载这个app,真正的支付宝是不支持沙箱测试码,不仅如此还在 沙箱账号 下提供一个测试账号给你(商家账号和买家账号),你用买家账号登录这个app就可以了,不要用你自己的支付宝账号哦

  开发程序

  发送数据时,需要按阿里的规则对数据加密,这个你也不要太操心,一般阿里也会提供一个SDK,相当于一个对数据进行加密的py文件,但是阿里官方提供了java等的,唯独没有python的,你可以到GitHub上去搜一个pay.py,并且这个是依赖pycryptodome模块的

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 urllib.parse import urlparse, parse_qs
from base64 import decodebytes, encodebytes
import json

class AliPay(object):
    """
    支付宝支付接口(PC端支付接口)
    """

    def __init__(self, appid, app_notify_url, app_private_key_path,
                 alipay_public_key_path, return_url, debug=False):
        self.appid = appid
        self.app_notify_url = app_notify_url
        self.app_private_key_path = app_private_key_path
        self.app_private_key = None
        self.return_url = return_url
        with open(self.app_private_key_path) as fp:
            self.app_private_key = RSA.importKey(fp.read())
        self.alipay_public_key_path = alipay_public_key_path
        with 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_url
            data["return_url"] = self.return_url

        return data

    def 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_string

    def 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_key
        signer = PKCS1_v1_5.new(key)
        signature = signer.sign(SHA256.new(unsigned_string))
        # base64 编码,转换为unicode表示并移除回车
        sign = encodebytes(signature).decode("utf8").replace("\n", "")
        return sign

    def _verify(self, raw_content, signature):
        # 开始计算签名
        key = self.alipay_public_key
        signer = PKCS1_v1_5.new(key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        if signer.verify(digest, decodebytes(signature.encode("utf8"))):
            return True
        return False

    def 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)

pay.py

  前端直接让输入个支付金额就可以了

    <form method="post">
        {% csrf_token %}
        <input type="text" name="price" placeholder="请输入要支付的金额">
        <input type="submit" value="支付">
    </form>

  后端走/index,在post分支下

  • 获取支付数据
  • 对价格、购买商品信息加密
  • 拼接支付宝支付扫码页面url
  • 跳转到支付扫码页面

  对于加密,就要用到刚才提到那个SDK了,在AliPay实例对象的时候需要提供APPID和支付成功后跳转url,公钥,私钥等信息

  但是公钥,私钥去哪里取呢?此时沙箱环境里是没有提供的,需要我们生成,那怎么生成了?

  点击沙箱里的 设置应用公钥,再点设置应用公钥,输入框上有个 查看密钥生成方法 点击一下,在使用方法里,点击下载WINDOWS,点击它下面bat工具就会自动生成 应用公钥,应用私钥(会有两个文件),而且你在沙箱那边上传应用公钥后,它还会自动生成一个支付宝公钥,而我们调用接口的时候,就要用到支付宝公钥和应用私钥

from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from utils.pay import AliPay
import time
from django.conf import settings

def aliPay():
    obj = AliPay(
        appid=settings.APPID,
        app_notify_url=settings.NOTIFY_URL,  # 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成)
        return_url=settings.RETURN_URL,  # 如果支付成功,重定向回到你的网站的地址。
        alipay_public_key_path=settings.PUB_KEY_PATH,  # 支付宝公钥
        app_private_key_path=settings.PRI_KEY_PATH,  # 应用私钥
        debug=True,  # 默认False,
    )
    return obj

def index(request):
    if request.method == ‘GET‘:
        return render(request,‘index.html‘)

    alipay = aliPay()

    # 对购买的数据进行加密
    money = float(request.POST.get(‘price‘)) #支付数保留两位小数
    out_trade_no = "x2" + str(time.time())  # 商户订单号
    # 1. 在数据库创建一条数据:状态(待支付)

    query_params = alipay.direct_pay(
        subject="充气式韩红",  # 商品简单描述
        out_trade_no= out_trade_no,  # 商户订单号
        total_amount=money,  # 交易金额(单位: 元 保留俩位小数)
    )

    pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)

    return redirect(pay_url)

  当然跳转支付页面后,商家怎么知道商品有没有支付成功呢?

  所以在上面过程中有个app_notify_url,就是用于支付成功后回调的url,而return_url则是在支付成功后跳转的url,支付宝要给你的回调url发送post请求,你就必须有公网IP,支付宝才能找到你

def pay_result(request):
    """
    支付完成后,跳转回的地址
    :param request:
    :return:
    """
    params = request.GET.dict()
    sign = params.pop(‘sign‘, None)  #获取签名

    alipay = aliPay()

    status = alipay.verify(params, sign)  #验证是否是阿里返回的数据

    if status:
        return HttpResponse(‘支付成功‘)
    return HttpResponse(‘支付失败‘)

@csrf_exempt
def update_order(request):
    """
    支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)
    :param request:
    :return:
    """
    if request.method == ‘POST‘:
        from urllib.parse import parse_qs

        body_str = request.body.decode(‘utf-8‘)
        post_data = parse_qs(body_str)

        post_dict = {}
        for k, v in post_data.items():
            post_dict[k] = v[0]

        alipay = aliPay()

        sign = post_dict.pop(‘sign‘, None)
        status = alipay.verify(post_dict, sign)
        if status:
            # 修改订单状态
            out_trade_no = post_dict.get(‘out_trade_no‘)
            print(out_trade_no)
            # 2. 根据订单号将数据库中的数据进行更新
            return HttpResponse(‘支付成功‘)
        else:
            return HttpResponse(‘支付失败‘)
    return HttpResponse(‘‘)

微信消息推送

  有这么一些业务场景,比如,你购买商品成功,向微信推送一条购买成功的消息...

  当然之前是通过短信通知,如果业务没处理好,短信成本还是很高的,而微信成本相对低得多

  一般是认证服务号以及以上级别的,才能推送消息,前提是你要关注我的服务号

  已认证服务号也是要营业执照的,所以测试的话,又要用沙箱环境

 沙箱环境地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

  用自己的微信登录后,就有appID,appsecret等信息提供给你,并且在下面还提供给测试公众号供你关注,旁边的用户列表就是每个用户微信id 唯一标识,微信在推送消息时,就通过这个唯一标识 来决定发送给哪个用户,当你扫了这个二维码点关注后,用户列表里就会多一条你的微信ID

  在开发业务场景下,我们希望微信ID能够在用户关注公众号后能够自动写入到我们程序的数据库中,而不是手动去微信公众平台复制,或者爬虫去爬,首先这样低效,并且你怎么确定哪个微信iD和你当前的用户有对应的关系?

  微信提供了这么一个接口,你只要传入appid,跳转url(回调地址),用户信息,就会帮生成一个url,前端用这个可以用生成二维码,供用户扫,扫完后就可以获取到用户微信id,并带上传入的用户信息,跳转到你指定的那个url,这个过程也是要公网IP的

  • 关注服务号
  • 根据用户生成 绑定个人账户二维码
  • 用户扫码,触发回调地址
  • 回调函数里,获取用户微信ID并更新

  注:要在微信公众平台下修改 网页帐号-网页授权获取用户基本信息,修改回调地址域名

  前端贴上公众号关注照片和生成 绑定个人账户二维码

{% load staticfiles %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div style="width: 600px;margin: 0 auto">
    <h1>请关注路飞学城服务号,并绑定个人用户(用于以后的消息提醒)</h1>
    <div>
        <h3>第一步:关注路飞学城微信服务号</h3>
        <img style="height: 100px;width: 100px" src="{% static "img/luffy.jpeg" %}">
    </div>
    <input type="button" value="下一步【获取绑定二维码】" onclick="getBindUserQcode()">
    <div>
        <h3>第二步:绑定个人账户</h3>
        <div id="qrcode" style="width: 250px;height: 250px;background-color: white;margin: 100px auto;"></div>
    </div>
</div>
<script src="{% static "js/jquery.min.js" %}"></script>
<script src="{% static "js/jquery.qrcode.min.js" %}"></script>
<script src="{% static "js/qrcode.js" %}"></script>
<script>
    function getBindUserQcode() {
        $.ajax({
            url: ‘/bind_qcode/‘,
            type: ‘GET‘,
            success: function (result) {
                console.log(result);
                $(‘#qrcode‘).empty().qrcode({text: result.data});  #生成二维码
            }
        });
    }
</script>

</body>
</html>
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):
    @functools.wraps(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 inner

def 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(
            appid=settings.WECHAT_CONFIG["app_id"], # ‘wx89085e915d351cae‘,
            redirect_uri=settings.WECHAT_CONFIG["redirect_uri"], # ‘http://47.93.4.198/test/‘,
            state=request.session[‘user_info‘][‘uid‘] # 为当前用户生成MD5值
        )
        ret[‘data‘] = access_url
    except Exception as e:
        ret[‘code‘] = 1001
        ret[‘msg‘] = str(e)

    return JsonResponse(ret)

def callback(request):
    """
    用户在手机微信上扫码后,微信自动调用该方法。
    用于获取扫码用户的唯一ID,以后用于给他推送消息。
    :param request:
    :return:
    """
    code = request.GET.get("code")

    # 用户md5值
    state = request.GET.get("state")

    # 获取该用户openId(用户唯一,用于给用户发送消息)
    res = requests.get(
        url="https://api.weixin.qq.com/sns/oauth2/access_token",
        params={
            "appid": ‘wx89085e915d351cae‘,
            "secret": ‘64f87abfc664f1d4f11d0ac98b24c42d‘,
            "code": code,
            "grant_type": ‘authorization_code‘,
        }
    ).json()
    # 获取的到openid表示用户授权成功
    openid = res.get("openid")
    if openid:
        models.UserInfo.objects.filter(uid=state).update(wx_id=openid)
        response = "<h1>授权成功 %s </h1>" % openid
    else:
        response = "<h1>用户扫码之后,手机上的提示</h1>"
    return HttpResponse(response)
  • 可以给微信用户推送消息

  发送前,我们还要去微信那边获取一个token,加上微信ID,才能给用户发消息

  消息也可以发送自定义消息和模板消息(提供变量占位和样式控制)

  不过模板消息,需要template_id,这个东西从哪拿呢?到微信公众平台  模板消息接口 下获取(没有,你就自行创建)

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 = None
        return access_token

    access_token = get_access_token()

    openid = models.UserInfo.objects.get(id=1).wx_id

    def send_custom_msg():
        body = {
            "touser": openid,
            "msgtype": "text",
            "text": {
                "content": ‘云姐好美呀‘
            }
        }
        response = requests.post(
            url="https://api.weixin.qq.com/cgi-bin/message/custom/send",
            params={
                ‘access_token‘: access_token
            },
            data=bytes(json.dumps(body, ensure_ascii=False), encoding=‘utf-8‘)
        )
        # 这里可根据回执code进行判定是否发送成功(也可以根据code根据错误信息)
        result = response.json()
        return result

    def 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": ‘0XbLbuNkn3wPPAYRVXM-MZ0gU0tPvVbsjfc1qoSH6CM‘,
                "data": {
                    "first": {
                        "value": "云姐",
                        "color": "#173177"
                    },
                    "keyword1": {
                        "value": "美女",
                        "color": "#173177"
                    },
                }
            }
        )
        result = res.json()
        return result

    result = send_template_msg()

    if result.get(‘errcode‘) == 0:
        return HttpResponse(‘发送成功‘)
    return HttpResponse(‘发送失败‘)

原文地址:https://www.cnblogs.com/xinsiwei18/p/10089052.html

时间: 2024-10-03 13:40:02

支付宝支付和微信消息推送的相关文章

微信消息推送

1.微信消息推送测试 微信公众号测试入口         ------->接口网址不好找啊 点击使用手机扫码进入,右键保存测试公众号二维码,如下(后面测试要用) 如果有多个用户扫码关注,则都会在右边显示出来,这里我自己先扫进去 另外还要注意这里的appid和appsercet,我们后面测试也需要使用 1.1给指定用户发送自己给定的消息 测试: 这里的access_token其实就像自己的门牌号一样,每次给用户发送消息时候,你都要指明自己的门牌号,才能向指定用户发送消息 import json i

企业微信消息推送

@Slf4j @Component public class WxMessageTask { @Autowired private CorpWechatConfig corpWechatConfig; @Autowired private RedisService redisService; @Autowired private RestTemplate restTemplate; /** * @Description: 企业微信消息推送 每天9点推送一次 * @Param: [] * @ret

django中实现微信消息推送

-公众号(不能主动给用户发消息) -认证的公众号:需要营业执照,需要交钱,可以发多篇文章 -未认证的公众号:一天只能发一篇文章 -服务号(微信推送) -需要申请,需要认证 -可以主动给用户推送消息 -能给推送的人,必须关注我的服务号 -沙箱环境 -企业号 -企业里用的: -你们所见的二维码:其实就是一个url地址 -咱们在前端通过url(https://open.weixin.qq.com/connect/oauth2.....)生成一个二维码 -注意*****修改:网页授权获取用户基本信息 一

企业微信消息推送接口

1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Nany.Web.Trans 6 { 7 public class AccessToken 8 { 9 private string Access_token; 10 11 public string access_token 12 { 13 get { return Access_token; } 14 set { Acc

C# MVC 微信支付之微信模板消息推送

微信支付之微信模板消息推送 今天我要跟大家分享的是"模板消息"的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不牛逼吗?现在的社会,人多多少少都有或轻或重的"强迫症".就是,看到有未读消息,都要去看一下.特别是现在的微信,大部分可以几个小时不看手机QQ有没有新消息来,但是这大部分人绝对做不到一个小时不看微信有没有消息来.现在的微信,真特么是神一样的存在,几乎人人手机上都会有微信.而且,如果你的公众号是服务号的话,这个

微信小程序之模板消息推送

最近在用sanic框架写微信小程序,其中写了一个微信消息推送,还挺有意思的,写了个小demo 具体见官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html 文档其实写的很详细清除了,包括返回数据的类型,报错信息 大致流程就是:调用微信小程序的接口,获取access_token,然后再调用发送模板信息的接口,发送消息 获取access_t

Java对接微信公众号模板消息推送

内容有点多,请耐心! 最近公司的有这个业务需求,又很凑巧让我来完成: 首先想要对接,先要一个公众号,再就是开发文档了:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html 不过请注意这一点 ok,我们继续:再来完成公众号的基本配置: 服务器地址(URL):必须以http://或https://开头,分别支持80端口和443端口.这个URL是很重要的,需要响应微信发送的token验证 令牌(To

微信公众号模版消息与小程序消息推送不同场景不同应用

1.公众号-插件-模板消息 图1.1 图1.2 图1.3 2.小程序-模板消息 图2.1 图2.2 图2.3 3.区别   1.推送条数不同 公众号的消息推送(以下简称公推)可以采用接口在后台调用接口无限向用户推送消息 小程序的消息推送(一下简称微推)只能允许开发者向用户在7天内推送有限条数的模板消息(引用官方的话)解释过来是:很难实现无限制推送用户消息(但是可以实现) 2.出现位置不同 公推消息形式会在该公众号下,与微信消息等级相同(如图1.2形式) 微推且消息出现在位置如图2.2,在"服务通

微信主动推送文本消息C#

1. 登陆,根据用户名和密码登陆到微信公众平台管理页面,获取token,模拟登陆请求地址:http://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN,2. 登陆后,获取用户所有的信息,地址:https://mp.weixin.qq.com/cgi-bin/contactmanage?t=user/index&token=,根据前面的token.3. 发送消息,地址:https://mp.weixin.qq.com/cgi-bin/singlesend?t=a