小程序支付

业务流程时序图 官方文档

步骤:

1. Openid

在小程序初次加载的时候就已经获取(详情见 小程序登录)

2. 生成商户订单

1.商品信息由小程序端提供
2.提供支付统一下单接口所需参数

3. 调用支付统一下单API

官方文档

4. 拿到返回预付单信息并处理

5. 再次签名

官方文档

案例:

小程序端

test.wxml
<button bind:tap="pay">支付</button>
test.js
Page({
pay:function(){
wx.request({
url: "http://127.0.0.1:8000/pay/",
method: "POST",
data:{"login_key":wx.getStorageSync("login_key")},
header: { "content-type": "application/json" },
success: function (e) {
console.log(e)
// 签权调起支付
wx.requestPayment({
'timeStamp': e.data.data.timeStamp,
'nonceStr': e.data.data.nonceStr,
'package': e.data.data.package,
'signType': e.data.data.signType,
'paySign': e.data.data.paySign,
'success': function (res)
{
console.log(res,"成功")
},
'fail': function (res)
{
console.log("支付失败",res)
},
})
}
})
},
})

后端 django

wx
├── settings.py # 小程序id,code2Session等配置
├── wx_login.py # 用于调用code2Session拿到openid等
└── WXBizDataCrypt.py # 获取用户授权信息的解密算法,官方下载
wx/settings.py
AppId="..."  微信分配的小程序id

AppSecret="..."

code2Session="https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code"
pay_mchid ='...' 微信配的商户id
pay_apikey = '...' 商户平台设置的秘钥key
项目/views.py
from rest_framework.views import  APIView
from rest_framework.response import Response
from django.core.cache import cache
import hashlib,time
import random
from app01.wx import settings
import requests
class Pay(APIView):
def post(self,request):
param=request.data
if param.get("login_key"):
#从redis中拿到小程序端login_key所对应得opendi&session_key值
openid,session_key=cache.get(param.get("login_key")).split("&")
self.openid=openid
# 获取用户IP
# 1.如果是Nginx做的负载就要HTTP_X_FORWARDED_FOR
if request.META.get('HTTP_X_FORWARDED_FOR'):
self.ip =request.META['HTTP_X_FORWARDED_FOR']
else:
# 2.如果没有用Nginx就用REMOTE_ADDR
self.ip = request.META['REMOTE_ADDR']
# 调用 生成商户订单 方法
data = self.pay()
return Response({"code":200,"msg":"ok","data":data})
else:
return Response({"code":200,"msg":"缺少参数"})
  # 生成随机字符串
def get_str(self):
str_all="1234567890abcdefghjklmasdwery" # 注意 开发活动功能时, 去掉1,i,0,o
nonce_str="".join(random.sample(str_all,20))
return nonce_str
  # 生成订单号
def get_order(self):
order_id=str(time.strftime("%Y%m%d%H%M%S"))
return order_id # 处理返回预付单方法
def xml_to_dict(self,data):
import xml.etree.ElementTree as ET
xml_dict={}
data_dic=ET.fromstring(data)
for item in data_dic:
xml_dict[item.tag]=item.text
return xml_dict # 获取sign签名方法
def get_sign(self):
data_dic = {
"nonce_str": self.nonce_str,
"out_trade_no": self.out_trade_no,
"spbill_create_ip": self.ip,
"notify_url": self.notify_url,
"openid": self.openid,
"body": self.body,
"trade_type": "JSAPI",
"appid": self.appid,
"total_fee": self.total_fee,
"mch_id": self.mch_id
}
sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
sign_str = f"{sign_str}&key={settings.pay_apikey}"
md5 = hashlib.md5()
md5.update(sign_str.encode("utf-8"))
return md5.hexdigest().upper() # 1.生成商户订单 提供 支付统一下单 所需参数
def pay(self):
self.appid=settings.AppId # appid 微信分配的小程序ID
self.mch_id=settings.pay_mchid # mch_id 微信分配的商户号
self.nonce_str=self.get_str() # 随机字符串
self.body="商品名" # 商品名一般由小程序端传到后端
self.out_trade_no=self.get_order() # 订单号
self.total_fee=1 # 订单总金额
self.spbill_create_ip=self.ip # 用户ip
self.notify_url="http://www.baidu.com" # 异步接收微信支付结果通知的回调地址
self.trade_type="JSAPI" # 固定写法
self.sign = self.get_sign() # 获取sign 签名
data=f'''
<xml>
<appid>{self.appid}</appid>
<body>{ self.body}</body>
<mch_id>{self.mch_id}</mch_id>
<nonce_str>{self.nonce_str}</nonce_str>
<notify_url>{self.notify_url}</notify_url>
<openid>{self.openid}</openid>
<out_trade_no>{self.out_trade_no}</out_trade_no>
<spbill_create_ip>{self.spbill_create_ip}</spbill_create_ip>
<total_fee>{self.total_fee}</total_fee>
<trade_type>{self.trade_type}</trade_type>
<sign>{self.sign}</sign>
</xml>
'''
# 2.支付统一下单接口
url="https://api.mch.weixin.qq.com/pay/unifiedorder"
# 3.返回预付单信息
response=requests.post(url,data.encode("utf-8"),headers={"content-type":"application/xml"})
res_data=self.xml_to_dict(response.content)
data=self.two_sign(res_data["prepay_id"]) # prepay_id 预支付订单回话标识
return data # 4.将组合数据再次签名
def two_sign(self,prepay_id):
timeStamp=str(int(time.time()))
nonceStr=self.get_str()
data_dict={
"appId":settings.AppId,
"timeStamp":timeStamp,
"nonceStr":nonceStr,
"package":f"prepay_id={prepay_id}",
"signType":"MD5"
}
sign_str = "&".join([f"{k}={data_dict[k]}" for k in sorted(data_dict)])
sign_str = f"{sign_str}&key={settings.pay_apikey}"
md5 = hashlib.md5()
md5.update(sign_str.encode("utf-8"))
sign=md5.hexdigest().upper()
data_dict["paySign"]=sign
data_dict.pop("appId")
# 5.返回支付参数到小程序端,小程序端获取所需参数向微信服务器发送 调起支付 方法
return data_dict
项目/urls.py
url(r'^pay/',views.Pay.as_view())

微信小程序 - 支付(后端代码实现)的更多相关文章

  1. 微信小程序支付之代码详解

    微信小程序自带的一套规则,类似vue语法,但是好多功能都集成在api中,给了很多初学者轮子,所以首先要熟悉这些api,忘记可照官网继续开发 这里主要说下微信小程序的支付,原理类似上篇介绍的公众网页支付 ...

  2. Java 后端微信小程序支付demo (网上说的坑里面基本上都有)

    Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...

  3. 微信小程序支付源码,后台服务端代码

    作者:尹华南,来自原文地址 微信小程序支付绕坑指南 步骤 A:小程序向服务端发送商品详情.金额.openid B:服务端向微信统一下单 C:服务器收到返回信息二次签名发回给小程序 D:小程序发起支付 ...

  4. 微信小程序支付C#后端源码

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...

  5. 微信小程序支付及退款流程详解

    微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...

  6. .NET Core 微信小程序支付——(统一下单)

    最近公司研发了几个电商小程序,还有一个核心的电商直播,只要是电商一般都会涉及到交易信息,离不开支付系统,这里我们统一实现小程序的支付流程(与服务号实现步骤一样). 目录1.开通小程序的支付能力2.商户 ...

  7. php 微信小程序支付

    php 微信小程序支付 直接贴代码: 前端测试按钮wxml: <view class="container"> <text class="name&qu ...

  8. 微信小程序支付步骤

    http://blog.csdn.net/wangsf789/article/details/53419781 最近开发微信小程序进入到支付阶段,一直以来从事App开发,所以支付流程还是熟记于心的.但 ...

  9. 微信小程序 PHP后端form表单提交实例详解

    微信小程序php后端form表单 https://www.cnblogs.com/tdalcn/p/7092716.html 1.小程序相对于之前的WEB+PHP建站来说,个人理解为只是将web放到了 ...

随机推荐

  1. Python thread (线程)

    线程 (thread) 操作系统最小的调度单位,是一串指令的集合 程序一开始就有一个主线程,新启动的线程和主线程之间互不影响,主线程启动子线程之后就相互独立(子线程也可以启动线程),无论子线程是否执行 ...

  2. CF1041C Coffee Break

    CF1041C Coffee Break 题目大意: 给定nn个数和一个kk,这nn个数都不超过mm 每次从没被去掉的数里面选一个数aa,去掉aa,然后可以任意一个b(b>a+k)b(b> ...

  3. 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)

    从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...

  4. etcd+https部署

    关闭防火墙 关闭selinux 下载所需的包(cfssl,生成证书工具) mkdir /usr/local/src/etcd/ cd /usr/local/src/etcd/ wget https:/ ...

  5. CSS3 clip裁剪动画

    CSS3 clip裁剪动画 下面是比较简单的例子 <pre><html><head><style type="text/css">i ...

  6. poj-2234 Matches Game Nim

    Matches Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13264   Accepted: 7712 Des ...

  7. laravel模型中非静态方法也能静态调用的原理

    刚开始用laravel模型时,为了方便一直写静态方法,进行数据库操作. <?php namespace App\Models; use Illuminate\Database\Eloquent\ ...

  8. Centos7编译安装Nginx+keepalived

    一.安装环境.主机信息及软件版本 Nginx:1.12.2keepalived:2.0.12时间同步(同步后确认各服务器时间是否一致,不一致需要修改一下时区) 关闭防火墙 二.编译安装Nginx 1. ...

  9. .NET基础知识(01)-值类型与引用类型

    常见面试题目: 1. 值类型和引用类型的区别? 2. 结构和类的区别? 3. delegate是引用类型还是值类型?enum.int[]和string呢? 4. 堆和栈的区别? 5. 什么情况下会在堆 ...

  10. 写入文件writelines 换行问题

    知识点:在python中没有数组的概念,有列表.元组.字典的概念 问题描述: 在写循环语句的时候,我需要把输出的列表存放到文件上,但是如果没有换行的话,存下的文件就是一坨的字. 所以在存入文件的时候就 ...