小程序支付

业务流程时序图 官方文档

步骤:

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="..."

AppSecret="..."

code2Session="https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code"

pay_mchid ='...'

pay_apikey = '...'

项目/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":"缺少参数"})
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_str(self):
str_all</span>=<span style="color: #800000;">"</span><span style="color: #800000;">1234567890abcdefghjklmasdwery</span><span style="color: #800000;">" # 注意 开发活动功能时, 去掉1,i,0,o</span><span style="color: #000000;">
nonce_str</span>=<span style="color: #800000;">""</span>.join(random.sample(str_all,20<span style="color: #000000;">))
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> nonce_str </span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_order(self):
order_id</span>=str(time.strftime(<span style="color: #800000;">"</span><span style="color: #800000;">%Y%m%d%H%M%S</span><span style="color: #800000;">"</span><span style="color: #000000;">))
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> order_id </span><span style="color: #008000;">#</span><span style="color: #008000;"> 处理返回预付单方法</span>
<span style="color: #0000ff;">def</span><span style="color: #000000;"> xml_to_dict(self,data):
</span><span style="color: #0000ff;">import</span><span style="color: #000000;"> xml.etree.ElementTree as ET
xml_dict</span>=<span style="color: #000000;">{}
data_dic</span>=<span style="color: #000000;">ET.fromstring(data)
</span><span style="color: #0000ff;">for</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> data_dic:
xml_dict[item.tag]</span>=<span style="color: #000000;">item.text
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> xml_dict </span><span style="color: #008000;">#</span><span style="color: #008000;"> 获取sign签名方法</span>
<span style="color: #0000ff;">def</span><span style="color: #000000;"> get_sign(self):
data_dic </span>=<span style="color: #000000;"> {
</span><span style="color: #800000;">"</span><span style="color: #800000;">nonce_str</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.nonce_str,
</span><span style="color: #800000;">"</span><span style="color: #800000;">out_trade_no</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.out_trade_no,
</span><span style="color: #800000;">"</span><span style="color: #800000;">spbill_create_ip</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.ip,
</span><span style="color: #800000;">"</span><span style="color: #800000;">notify_url</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.notify_url,
</span><span style="color: #800000;">"</span><span style="color: #800000;">openid</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.openid,
</span><span style="color: #800000;">"</span><span style="color: #800000;">body</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.body,
</span><span style="color: #800000;">"</span><span style="color: #800000;">trade_type</span><span style="color: #800000;">"</span>: <span style="color: #800000;">"</span><span style="color: #800000;">JSAPI</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">appid</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.appid,
</span><span style="color: #800000;">"</span><span style="color: #800000;">total_fee</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.total_fee,
</span><span style="color: #800000;">"</span><span style="color: #800000;">mch_id</span><span style="color: #800000;">"</span><span style="color: #000000;">: self.mch_id
}
sign_str </span>= <span style="color: #800000;">"</span><span style="color: #800000;">&amp;</span><span style="color: #800000;">"</span>.join([f<span style="color: #800000;">"</span><span style="color: #800000;">{k}={data_dic[k]}</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">for</span> k <span style="color: #0000ff;">in</span><span style="color: #000000;"> sorted(data_dic)])
sign_str </span>= f<span style="color: #800000;">"</span><span style="color: #800000;">{sign_str}&amp;key={settings.pay_apikey}</span><span style="color: #800000;">"</span><span style="color: #000000;">
md5 </span>=<span style="color: #000000;"> hashlib.md5()
md5.update(sign_str.encode(</span><span style="color: #800000;">"</span><span style="color: #800000;">utf-8</span><span style="color: #800000;">"</span><span style="color: #000000;">))
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> md5.hexdigest().upper() </span><span style="color: #ff0000;"># 1.生成商户订单 提供 支付统一下单 所需参数</span>
<span style="color: #0000ff;">def</span><span style="color: #000000;"> pay(self):
self.appid</span>=<span style="color: #000000;">settings.AppId
self.mch_id</span>=<span style="color: #000000;">settings.pay_mchid
self.nonce_str</span>=<span style="color: #000000;">self.get_str()
self.body</span>=<span style="color: #800000;">"商品名</span><span style="color: #800000;">"</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 商品名一般由小程序端传到后端</span>
self.out_trade_no=<span style="color: #000000;">self.get_order()
self.total_fee</span>=1<span style="color: #000000;">
self.spbill_create_ip</span>=<span style="color: #000000;">self.ip
self.notify_url</span>=<span style="color: #800000;">"</span><span style="color: #800000;">http://www.baidu.com</span><span style="color: #800000;">"</span><span style="color: #000000;">
self.trade_type</span>=<span style="color: #800000;">"</span><span style="color: #800000;">JSAPI</span><span style="color: #800000;">"</span><span style="color: #000000;">
self.sign </span>= self.get_sign() <span style="color: #008000;">#</span><span style="color: #008000;"> 获取sign 签名</span>
data=f<span style="color: #800000;">'''</span><span style="color: #800000;">
&lt;xml&gt;
&lt;appid&gt;{self.appid}&lt;/appid&gt;
&lt;body&gt;{ self.body}&lt;/body&gt;
&lt;mch_id&gt;{self.mch_id}&lt;/mch_id&gt;
&lt;nonce_str&gt;{self.nonce_str}&lt;/nonce_str&gt;
&lt;notify_url&gt;{self.notify_url}&lt;/notify_url&gt;
&lt;openid&gt;{self.openid}&lt;/openid&gt;
&lt;out_trade_no&gt;{self.out_trade_no}&lt;/out_trade_no&gt;
&lt;spbill_create_ip&gt;{self.spbill_create_ip}&lt;/spbill_create_ip&gt;
&lt;total_fee&gt;{self.total_fee}&lt;/total_fee&gt;
&lt;trade_type&gt;{self.trade_type}&lt;/trade_type&gt;
&lt;sign&gt;{self.sign}&lt;/sign&gt;
&lt;/xml&gt;
</span><span style="color: #800000;">'''</span>
<span style="color: #ff0000;"># 2.支付统一下单</span>
url=<span style="color: #800000;">"</span><span style="color: #800000;">https://api.mch.weixin.qq.com/pay/unifiedorder</span><span style="color: #800000;">"</span>
<span style="color: #ff0000;"># 3.返回预付单信息</span>
response=requests.post(url,data.encode(<span style="color: #800000;">"</span><span style="color: #800000;">utf-8</span><span style="color: #800000;">"</span>),headers={<span style="color: #800000;">"</span><span style="color: #800000;">content-type</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">application/xml</span><span style="color: #800000;">"</span><span style="color: #000000;">})
res_data</span>=<span style="color: #000000;">self.xml_to_dict(response.content)
data</span>=self.two_sign(res_data[<span style="color: #800000;">"</span><span style="color: #800000;">prepay_id</span><span style="color: #800000;">"</span><span style="color: #000000;">])
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> data </span><span style="color: #ff0000;"># 4.将组合数据再次签名</span>
<span style="color: #0000ff;">def</span><span style="color: #000000;"> two_sign(self,prepay_id):
timeStamp</span>=<span style="color: #000000;">str(int(time.time()))
nonceStr</span>=<span style="color: #000000;">self.get_str()
data_dict</span>=<span style="color: #000000;">{
</span><span style="color: #800000;">"</span><span style="color: #800000;">appId</span><span style="color: #800000;">"</span><span style="color: #000000;">:settings.AppId,
</span><span style="color: #800000;">"</span><span style="color: #800000;">timeStamp</span><span style="color: #800000;">"</span><span style="color: #000000;">:timeStamp,
</span><span style="color: #800000;">"</span><span style="color: #800000;">nonceStr</span><span style="color: #800000;">"</span><span style="color: #000000;">:nonceStr,
</span><span style="color: #800000;">"</span><span style="color: #800000;">package</span><span style="color: #800000;">"</span>:f<span style="color: #800000;">"</span><span style="color: #800000;">prepay_id={prepay_id}</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #800000;">"</span><span style="color: #800000;">signType</span><span style="color: #800000;">"</span>:<span style="color: #800000;">"</span><span style="color: #800000;">MD5</span><span style="color: #800000;">"</span><span style="color: #000000;">
}
sign_str </span>= <span style="color: #800000;">"</span><span style="color: #800000;">&amp;</span><span style="color: #800000;">"</span>.join([f<span style="color: #800000;">"</span><span style="color: #800000;">{k}={data_dict[k]}</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">for</span> k <span style="color: #0000ff;">in</span><span style="color: #000000;"> sorted(data_dict)])
sign_str </span>= f<span style="color: #800000;">"</span><span style="color: #800000;">{sign_str}&amp;key={settings.pay_apikey}</span><span style="color: #800000;">"</span><span style="color: #000000;">
md5 </span>=<span style="color: #000000;"> hashlib.md5()
md5.update(sign_str.encode(</span><span style="color: #800000;">"</span><span style="color: #800000;">utf-8</span><span style="color: #800000;">"</span><span style="color: #000000;">))
sign</span>=<span style="color: #000000;">md5.hexdigest().upper()
data_dict[</span><span style="color: #800000;">"</span><span style="color: #800000;">paySign</span><span style="color: #800000;">"</span>]=<span style="color: #000000;">sign
data_dict.pop(</span><span style="color: #800000;">"</span><span style="color: #800000;">appId</span><span style="color: #800000;">"</span><span style="color: #000000;">)
</span><span style="color: #ff0000;"># 5.返回支付参数到小程序端,小程序端获取所需参数向微信服务器发送 调起支付 方法</span>
<span style="color: #0000ff;">return</span> data_dict</pre>
项目/urls.py
url(r'^pay/',views.Pay.as_view())

微信小程序支付功能讲解(2)的更多相关文章

  1. 微信小程序支付功能讲解(1)

    前言:虽然小程序做过很多,但是一直觉得微信支付功能很是神秘,现在终于有机会接触心里还是有点小激动的,经过一番折腾发现支付也不过如此,在此记录下支付功能的实现过程 小程序的官方文档介绍到发起微信支付即调 ...

  2. 微信小程序支付功能讲解

    前言:虽然小程序做过很多,但是一直觉得微信支付功能很是神秘,现在终于有机会接触心里还是有点小激动的,经过一番折腾发现支付也不过如此,在此记录下支付功能的实现过程 小程序的官方文档介绍到发起微信支付即调 ...

  3. 微信小程序支付功能 C# .NET开发

    微信小程序支付功能的开发的时候坑比较多,不过对于钱的事谨慎也是好事.网上关于小程序支付的实例很多,但是大多多少有些问题,C#开发的更少.此篇文档的目的是讲开发过程中遇到的问题做一个备注,也方便其他开发 ...

  4. 微信小程序支付功能前端流程

    只是分享一下小程序支付功能的前端流程和代码, 仅供参考(使用的是uni app). handleCreate () { /** 第一步:前台将商品数据发送到后台,后台创建订单入库并返回订单id等信息 ...

  5. 微信小程序 支付功能(前端)的实现

    只提供微信小程序端代码: var app = getApp(); Page({ data: {}, onLoad: function (options) { // 页面初始化 options为页面跳转 ...

  6. Python实现微信小程序支付功能

    由于最近自己在做小程序的支付,就在这里简单介绍一下讲一下用python做小程序支付这个流程.当然在进行开发之前还是建议读一下具体的流程,清楚支付的过程. 1.支付交互流程 当然具体的参数配置可以参考官 ...

  7. 微信小程序 支付功能 服务器端(TP5.1)实现

    首先下载微信支付SDK ,将整个目录的文件放在 /application/extend/WxPay 目录下 在使用SDK之前我们需要对 WxPay.Config.php 进行配置 <?php n ...

  8. 微信小程序支付功能完整流程

    支付流程 整个支付流程分为四个步骤: 获取令牌token 创建订单 预支付,获取支付参数对象pay 发起微信支付 收尾工作.跳转到订单页面,删除购物车中已购买的商品 请求方式:POST 整个支付过程中 ...

  9. 微信小程序支付功能

    API:wx.requestPayment() { } https://blog.csdn.net/qishubiao/article/details/80804052

随机推荐

  1. JavaScript工具库

    jPublic 交流QQ群:1017567122 前言 在我们开发项目的时候,无论项目规模大小,在所难免会写一些工具型函数来解决一些问题,随着项目开发和维护的时间越来越长,这些工具型函数会越来越多,同 ...

  2. Windows10安装Elasticsearch IK分词插件

    安装插件 cmd切换到Elasticsearch安装目录下 C:\Users\Administrator>D: D:\>cd D:\Program Files\Elastic\Elasti ...

  3. Windows 2012 R2 安装RD服务

    默认只能同时允许2个用户连接,如果希望更多用户同时连接服务器,需要开启并激活远程桌面服务.参考:https://jingyan.baidu.com/article/9f7e7ec0f5a8686f28 ...

  4. 教你如何在5分钟轻松部署squid正向代理

    正向代理是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返 ...

  5. 如何写一个Python万能装饰器,既可以装饰有参数的方法,也可以装饰无参数方法,或者有无返回值都可以装饰

    Python中的装饰器,可以有参数,可以有返回值,那么如何能让这个装饰器既可以装饰没有参数没有返回值的方法,又可以装饰有返回值或者有参数的方法呢?有一种万能装饰器,代码如下: def decorate ...

  6. MyBatis的ResultMapping和ResultMap

    MyBatis的ResultMapping和ResultMap Effective java 第3版中描述的Builder模式 Java设计模式14:建造者模式 2个类都使用了Builder来构建对象 ...

  7. (day69)axios、配置ElementUI、配置jQuery和Bootstrap、Django中的CORS问题

    目录 一.Vue的ajax插件:axios 二.Django中的CORS跨域问题 (一)同源策略 (二)解决方式(cors模块) 三.Vue配置ElementUI 四.Vue配置jQuery和Boot ...

  8. nginx 反向代理之 proxy_pass

    格式很简单: proxy_pass URL; 其中URL包含:传输协议(http://, https://等).主机名(域名或者IP:PORT).uri. 示例如下: proxy_pass http: ...

  9. UI设计---初来乍到

    2019.12.1   今天学习两节 实现自己既定的目标,必须能耐得住寂寞单干. PS下载 给大家分享一个2019ps教程,提取码:ywnl 或扫描二维码 迅捷思维导图:使用" Enter  ...

  10. 在windows桌面上创建一个文件夹

    用dos命令创建 md [文件路径][文件名] C:\Users\admin>md  C:\Users\admin\desktop\test 刷新一下桌面,就可以看见桌面上创建了一个名为test ...