微信小程序 - 支付(后端代碼實現)


小程序支付

業務流程時序圖 官方文檔

 

 

 步驟:

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM