• 支付宝支付---流程详解


    👏👏👏

    哈喽!大家好,我是【太阳打伞】,一位热爱分享各种技术的博主!😍😍😍

    ⭐【太阳打伞】的创作宗旨:每一条命令都亲自执行过,每一行代码都实际运行过,每一种方法都真实实践过,每一篇文章都良心制作过。✊✊✊

    ⭐【太阳打伞】的博客中所有涉及命令、代码的地方,除了提供图片供大家参考,另外会在图片下方提供一份纯文本格式的命令或者代码方便大家粘贴复制直接执行命令或者运行代码。🤝🤝🤝

    ⭐如果你对技术有着浓厚的兴趣,欢迎关注【太阳打伞】,欢迎大家和我一起交流。😘😘😘

    ❤️❤️❤️感谢各位朋友接下来的阅读❤️❤️❤️
     

    流程图:

     !!!:效果内容在最下方,一定要看呀。

    第一步:

    登录支付宝,打开控制台,进入研发服务

     

     第二步:

    进入沙箱,生成自己的私钥,支付宝公钥

    将支付宝公钥和自己私钥存放到.txt文件中

     第三步:

    拿到自己的支付宝沙箱应用id,和   买家账号:xxxxxxxxxxxx
                                                            登录密码111111
                                                            支付密码111111,

    买家账号等到支付时使用!

    第四步:

    后端代码实现:

    创建alipay.py文件

    我采用的是Tornado框架实现的!!!

    1. from datetime import datetime
    2. from Crypto.PublicKey import RSA
    3. from Crypto.Signature import PKCS1_v1_5
    4. from Crypto.Hash import SHA256
    5. from urllib.parse import quote_plus
    6. from urllib.parse import urlparse, parse_qs
    7. from base64 import decodebytes, encodebytes
    8. import json
    9. from tornado import httpclient
    10. class AliPay:
    11. """
    12. 支付宝支付接口(PC端支付接口)
    13. """
    14. def __init__(self, appid, app_notify_url, app_private_key_path,
    15. alipay_public_key_path, return_url, debug=True):
    16. self.appid = appid
    17. self.app_notify_url = app_notify_url
    18. self.app_private_key_path = app_private_key_path
    19. self.app_private_key = None
    20. self.return_url = return_url
    21. with open(self.app_private_key_path) as fp:
    22. self.app_private_key = RSA.importKey(fp.read())
    23. self.alipay_public_key_path = alipay_public_key_path
    24. with open(self.alipay_public_key_path) as fp:
    25. self.alipay_public_key = RSA.importKey(fp.read())
    26. if debug is True:
    27. self.__gateway = "https://openapi.alipaydev.com/gateway.do"
    28. else:
    29. self.__gateway = "https://openapi.alipay.com/gateway.do"
    30. # 商户订单号out_trade_no
    31. def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
    32. biz_content = {
    33. "subject": subject,
    34. "out_trade_no": out_trade_no,
    35. "total_amount": total_amount,
    36. "product_code": "FAST_INSTANT_TRADE_PAY",
    37. # "qr_pay_mode":4
    38. }
    39. biz_content.update(kwargs)
    40. data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
    41. return self.sign_data(data)
    42. # 查询订单状态方法
    43. async def api_alipay_trade_query(self,out_trade_no=None,**kwargs):
    44. biz_content = {
    45. "out_trade_no": out_trade_no
    46. }
    47. biz_content.update(**kwargs)
    48. data = self.build_body("alipay.trade.query", biz_content)
    49. url = self.__gateway + "?" + self.sign_data(data)
    50. res = await httpclient.AsyncHTTPClient().fetch(url,method='GET',validate_cert=False,connect_timeout=30.0, request_timeout=30.0)
    51. res = json.loads(res.body.decode())
    52. return res
    53. #请求支付宝退款接口
    54. async def api_alipay_trade_refund(self, refund_amount, out_trade_no=None, trade_no=None, **kwargs):
    55. biz_content = {
    56. "refund_amount": refund_amount
    57. }
    58. biz_content.update(**kwargs)
    59. if out_trade_no:
    60. biz_content["out_trade_no"] = out_trade_no
    61. if trade_no:
    62. biz_content["trade_no"] = trade_no
    63. data = self.build_body("alipay.trade.refund", biz_content)
    64. url = self.__gateway + "?" + self.sign_data(data)
    65. res = await httpclient.AsyncHTTPClient().fetch(url,method='GET',validate_cert=False,connect_timeout=30.0, request_timeout=30.0)
    66. res = json.loads(res.body.decode())
    67. return res
    68. def build_body(self, method, biz_content, return_url=None):
    69. data = {
    70. "app_id": self.appid,
    71. "method": method,
    72. "charset": "utf-8",
    73. "sign_type": "RSA2",
    74. "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    75. "version": "1.0",
    76. "biz_content": biz_content
    77. }
    78. if return_url is not None:
    79. data["notify_url"] = self.app_notify_url
    80. data["return_url"] = self.return_url
    81. return data
    82. def sign_data(self, data):
    83. data.pop("sign", None)
    84. # 排序后的字符串
    85. unsigned_items = self.ordered_data(data)
    86. unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
    87. sign = self.sign(unsigned_string.encode("utf-8"))
    88. # ordered_items = self.ordered_data(data)
    89. quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)
    90. # 获得最终的订单信息字符串
    91. signed_string = quoted_string + "&sign=" + quote_plus(sign)
    92. return signed_string
    93. def ordered_data(self, data):
    94. complex_keys = []
    95. for key, value in data.items():
    96. if isinstance(value, dict):
    97. complex_keys.append(key)
    98. # 将字典类型的数据dump出来
    99. for key in complex_keys:
    100. data[key] = json.dumps(data[key], separators=(',', ':'))
    101. return sorted([(k, v) for k, v in data.items()])
    102. def sign(self, unsigned_string):
    103. # 开始计算签名
    104. key = self.app_private_key
    105. signer = PKCS1_v1_5.new(key)
    106. signature = signer.sign(SHA256.new(unsigned_string))
    107. # base64 编码,转换为unicode表示并移除回车
    108. sign = encodebytes(signature).decode("utf8").replace("\n", "")
    109. return sign
    110. def _verify(self, raw_content, signature):
    111. # 开始计算签名
    112. key = self.alipay_public_key
    113. signer = PKCS1_v1_5.new(key)
    114. digest = SHA256.new()
    115. digest.update(raw_content.encode("utf8"))
    116. if signer.verify(digest, decodebytes(signature.encode("utf8"))):
    117. return True
    118. return False
    119. def verify(self, data, signature):
    120. if "sign_type" in data:
    121. sign_type = data.pop("sign_type")
    122. # 排序后的字符串
    123. unsigned_items = self.ordered_data(data)
    124. message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
    125. return self._verify(message, signature)

    第五步:

    写pay.py主文件:

    1. import datetime
    2. import logging
    3. import decimal
    4. from base import BaseHandler
    5. from tornado.web import url
    6. from db import UserModel,OrderModel
    7. from user import BaseMange
    8. # 充值
    9. from alipay import AliPay
    10. from utils import jwt_auth
    11. # 钱包
    12. class WalletHandler(BaseMange):
    13. """创建订单"""
    14. @jwt_auth
    15. async def post(self):
    16. _where = "model.uid == {}".format(self._cuser.id)
    17. orders = await self.get_all_where(OrderModel,_where)
    18. return self.finish({"errcode":0,"data":orders})
    19. @jwt_auth
    20. async def get(self):
    21. # 查询用户余额
    22. user = await self.get_one_obj(UserModel, self._cuser.id)
    23. return self.finish({'errcode': 0, 'data': user.wallet})
    24. class PayHandler(BaseMange):
    25. # 转跳地址
    26. @jwt_auth
    27. async def get(self):
    28. alipay = AliPay(
    29. appid='xxxxxxxxxx', # 你的支付宝沙箱应用的id
    30. app_private_key_path='./keys/app_private_2048.txt', # 你的私钥
    31. alipay_public_key_path='./keys/alipay_public_2048.txt', # 支付宝公钥,
    32. app_notify_url="http://127.0.0.1:8080/wallet", # 回调地址
    33. return_url='http://127.0.0.1:8080/pay',
    34. debug=True # 请求来到支付宝沙箱)
    35. )
    36. # 3.创建订单
    37. order_id = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + "_%s" % self._cuser.id
    38. subject = self.get_argument("subject",None)
    39. # 订单编号
    40. total_amount= self.get_argument("total_amount",None)
    41. # res = alipay.direct_pay(subject,order_id,total_amount)
    42. # print(res)
    43. # pay_url = "https://openapi.alipaydev.com/gateway.do?"+res # 支付宝网关地址(沙箱应用)
    44. # return self.finish({'errcode': 0, 'data': pay_url})
    45. """创建订单"""
    46. try:
    47. # 创建订单信息
    48. order = {"order_id": order_id, "uid_id": self._cuser.id, "total_amount": float(total_amount)}
    49. order = await self.create(OrderModel, order)
    50. res = alipay.direct_pay(subject, order_id, total_amount)
    51. print(res)
    52. pay_url = "https://openapi.alipaydev.com/gateway.do?" + res # 支付宝网关地址(沙箱应用)
    53. # print(pay_url)
    54. return self.finish({'errcode': 0, 'data': pay_url})
    55. except Exception as e:
    56. logging.error("create order error, reason is %s" % e)
    57. return self.finish({'errcode': 1, 'msg': "交易出错!"})
    58. @jwt_auth
    59. async def post(self):
    60. order_id = self.get_argument("out_trade_no", None) # 订单编号
    61. _where = "(model.order_id=='{}')".format(order_id)
    62. alipay = AliPay(
    63. appid='xxxxxxxxxx', # 你的支付宝沙箱应用的id
    64. app_private_key_path='./keys/app_private_2048.txt', # 你的私钥
    65. alipay_public_key_path='./keys/alipay_public_2048.txt', # 支付宝公钥,
    66. app_notify_url="http://127.0.0.1:8080/wallet", # 回调地址
    67. return_url='http://127.0.0.1:8080/pay',
    68. debug=True # 请求来到支付宝沙箱)
    69. )
    70. res = await alipay.api_alipay_trade_query(out_trade_no=order_id)
    71. print(res)
    72. res = res['alipay_trade_query_response']
    73. if res['code'] == '10000':
    74. try:
    75. order = await self.get_one_where(OrderModel, _where)
    76. # 修改订单的状态
    77. order.trade_no = res['trade_no']
    78. order.total_amount = res['total_amount']
    79. order.status = 1
    80. order.record = res["send_pay_date"]
    81. await self.application.objects.update(order)
    82. user = await self.get_one_obj(UserModel, self._cuser.id)
    83. user.wallet = user.wallet + decimal.Decimal(res['total_amount'])
    84. await self.application.objects.update(user)
    85. return self.finish({'errcode': 0, 'msg': "充值成功"})
    86. except Exception as e:
    87. print(e)
    88. return self.finish({'errcode': 1, 'msg': "未找到订单交易!"})
    89. else:
    90. return self.finish({'errcode': 2, 'msg': "支付失败!"})
    91. urlpatterns = [
    92. url('/pay/', PayHandler),
    93. url('/wallet/', WalletHandler),
    94. ]

    第六步:

    前端代码实现

    我使用的是Vue.3

    文件名是:wallet.vue

    1. <template>
    2. <div class="container">
    3. <a-layout>
    4. <a-layout-sider>
    5. <mymenu>mymenu>
    6. a-layout-sider>
    7. <a-layout>
    8. <h2>充值页面h2>
    9. <h3>我的钱包h3>
    10. <p>
    11. <a-col :span="22">
    12. <a-statistic title="钱包余额" :precision="2" :value= wallet />
    13. a-col>
    14. p>
    15. <div class="components-input-demo-presuffix">
    16. <h2>钱包充值h2>
    17. <p>请输入充值金额:
    18. <a-input v-model:value="value" prefix="¥" suffix="RMB" placeholder="请输入充值金额" />
    19. p>
    20. <p>
    21. <a-button type="primary" @click="get_pay()">支付宝充值a-button>
    22. <a-button type="">微信充值a-button>
    23. p>
    24. div>
    25. <p>用户订单表p>
    26. <p><table>
    27. <tr>
    28. <th>订单编号th>
    29. <th>创建时间th>
    30. <th>支付方式th>
    31. <th>备注th>
    32. <th>支付状态th>
    33. tr>
    34. <tr v-for="(j,i) in orderlist" :key="i">
    35. <td>{{j.order_id}}td>
    36. <td>{{j.create_time}}td>
    37. <td>{{j.pay_method}}td>
    38. <td>{{j.record}}td>
    39. <td v-if="j.status==0">待支付td>
    40. <td v-if="j.status==1">已支付td>
    41. <td v-if="j.status==3">已取消td>
    42. tr>
    43. table>p>
    44. a-layout>
    45. a-layout>
    46. div>
    47. template>
    48. <script>
    49. // 导入子组件
    50. import mymenu from "./mymenu.vue";
    51. import { message } from "ant-design-vue";
    52. export default {
    53. data() {
    54. return {
    55. collapsed: false,
    56. selectedKeys: ["1"],
    57. visible:false,
    58. money:'',
    59. id:'',
    60. wallet:0,
    61. value:50,
    62. orderlist:[]
    63. };
    64. },
    65. //声明组件
    66. components: {
    67. mymenu,
    68. },
    69. methods: {
    70. pay(id){
    71. this.visible = true
    72. // this.id = id
    73. },
    74. // 充值请求
    75. get_pay() {
    76. this.myaxios(this.baseurl + "pay/", "get",{"subject":"钱包充值","total_amount":this.value}).then(data => {
    77. console.log(data);
    78. if (data.errcode === 0) {
    79. window.location.href=data.data
    80. }
    81. });
    82. },
    83. get_wallet() {
    84. this.myaxios(this.baseurl + "wallet/", "get").then(data => {
    85. console.log(data);
    86. if (data.errcode === 0) {
    87. this.wallet = data.data
    88. }
    89. });
    90. },
    91. get_orderlist(){
    92. this.myaxios(this.baseurl + "wallet/", "post").then(data => {
    93. console.log(data);
    94. if (data.errcode === 0) {
    95. this.orderlist = data.data
    96. }
    97. });
    98. }
    99. },
    100. created() {
    101. this.get_wallet()
    102. this.get_orderlist()
    103. },
    104. mounted() {},
    105. };
    106. script>
    107. <style scoped>
    108. @import url("../assets/style.css");
    109. style>

    充值请求:

    文件名是:pay.vue

    1. <template>
    2. <div class="container">
    3. <a-layout>
    4. <a-layout-sider>
    5. <mymenu>mymenu>
    6. a-layout-sider>
    7. <a-layout>
    8. <h2>充值页面h2>
    9. a-layout>
    10. a-layout>
    11. div>
    12. template>
    13. <script>
    14. // 导入子组件
    15. import mymenu from "./mymenu.vue";
    16. import { message } from "ant-design-vue";
    17. import { createFromIconfontCN } from '@ant-design/icons-vue';
    18. const IconFont = createFromIconfontCN({
    19. scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js',
    20. });
    21. export default {
    22. data() {
    23. return {
    24. collapsed: false,
    25. selectedKeys: ["1"],
    26. };
    27. },
    28. //声明组件
    29. components: {
    30. mymenu,
    31. },
    32. methods: {
    33. // 充值请求
    34. check_order(){
    35. this.myaxios(this.baseurl + "pay/", "post",{"out_trade_no":this.$route.query.out_trade_no,"trade_no":this.$route.query.trade_no,"total_amount":this.$route.query.total_amount,"timestamp":this.$route.query.timestamp}).then(data => {
    36. console.log(data);
    37. if (data.errcode === 0) {
    38. this.$message.success(data.msg)
    39. window.location.href="/wallet"
    40. }else{
    41. this.$message.error(data.msg)
    42. window.location.href="/wallet"
    43. }
    44. });
    45. }
    46. },
    47. created() {
    48. this.check_order()
    49. },
    50. mounted() {},
    51. };
    52. script>
    53. <style scoped>
    54. @import url("../assets/style.css");
    55. style>

    第七步:

    数据库内容,字段名

    订单表:

     用户表:记得写钱包字段哦

     效果内容(show):

     点击支付宝充值:

     输入从沙箱获得的支付宝账号和密码。

    点击确认付款!

    后面还让输入支付密码!!!

    钱包到账啦:

     

     这个就是支付宝支付,代码有效,修改即用!!!

     

  • 相关阅读:
    二维矩阵内的BFS搜索
    递归关系的渐进时间复杂度推导
    笔记(二)图的基本表示【斯坦福CS224W图机器学习】
    在java中使用Reactor 项目中的一个类Mono,用于表示异步单值操作
    如何提升网站运营效率
    haproxy,nginx,keepalived综合运用
    springboot采用协同过滤算法的家政服务平台的设计与实现毕业设计源码260839
    SCI英语论文长难句攻略
    图论——并查集
    Java基础练习(矩阵的加减乘除运算)
  • 原文地址:https://blog.csdn.net/justzcy/article/details/126469524