前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微信支付接口对接

微信支付接口对接

作者头像
用户4945346
发布2020-06-16 10:12:32
2.8K0
发布2020-06-16 10:12:32
举报
文章被收录于专栏:pythonista的日常pythonista的日常

最近对接了安卓开发,涉及到了微信支付,需要调取微信 app 支付相关的接口,目前我们项目中使用的是微信普通商户版的。我们开发的安卓 APP 调用微信提供的SDK调用微信支付模块,安卓 APP 会跳转到微信中完成支付,支付完后跳回到安卓APP内,最后展示支付结果。我们后端涉及到的接口主要是统一下单接口、调起支付接口,支付结果通知接口。

首先按照统微信统一下单接口文档,把所有必填参数发送给统一下单接口在微信支付服务后台生成预支付交易单,如果成功统一下单接口会返回给你一个prepayid(这个很重要),然后再按照微信支付接口文档要求,把必填的字段以及之前返回给你的 prepay_id 发送给安卓 app 端,安卓 app 会调取微信支付接口。微信会根据你之前在统一下单接口中传递的 notify_url 字段,回调你的接口(这个接口必须是线上环境,外界可以访问的),通知你支付是否成功,参考支付结果通知。微信 app 支付的流程大体是这样的。需要注意的是签名的生成,必须要把参数按照 ASCII 码进行排序。

代码语言:javascript
复制
import datetime
import logging
import time
import uuid
from decimal import Decimal

import requests
from django.db import transaction
from wechatpy.pay.utils import calculate_signature


def order_wx_app_pay(main_order):
    """
    订单微信APP支付
    :param main_order:
    :return:
    """
    unpaid_amount = main_order.get_unpaid_amount()
    if unpaid_amount <= 0:
        return False, ErrorCode.NOT_TO_PAY_ORDER
    # company = main_order.company
    # account = company.wx_account
    # sub_mch_id = account.mchid
    # if not sub_mch_id:
    #     return False, ErrorCode.NOT_COMPANY_MCH_ID
    # ip = self.request.headers.get('X-Real-Ip', 0) or self.request.remote_ip
    ip = "127.0.0.1"
    nonce_str = uuid.uuid1().hex.upper()
    notify_url = WxConfig.NOTIFY_URL
    body = "商品名称"
    req_args = {
        "appid": WxConfig.WX_PAY_APP_ID_OFFICAL,  # 商户的APPID
        "mch_id": WxConfig.MCH_ID,  # 商户号
        "nonce_str": nonce_str,  # 随机字符串
        "body": body.encode("utf-8"),  # 商品描述
        "out_trade_no": main_order.order_number,  # 商户订单号
        "total_fee": int(unpaid_amount * 100),  # 总金额
        "spbill_create_ip": ip,  # 终端IP
        "notify_url": notify_url,  # 通知地址
        "trade_type": "APP"  # 交易类型
    }
    # 生成签名
    req_sign = calculate_signature(req_args, WxConfig.WX_PAY_API_KEY)
    req_args['sign'] = req_sign
    req_xml = trans_dict_to_xml(req_args)
    # 定义返回信息
    return_code, return_msg, result_code = None, None, None
    prepay_id = None
    #  调用微信统一下单接口,正常返回prepay_id
    try:
        response = requests.post(url=WxConfig.URL_PAY_WX_MP, data=req_xml)
        response.encoding = "utf8"
        result = response.text
        result = trans_xml_to_dict(result)
        return_code = result['return_code']
        return_msg = result['return_msg']
        if return_code == "SUCCESS":
            result_code = result['result_code']
            if result_code == 'SUCCESS':
                prepay_id = result.get('prepay_id')
            else:
                err_code_des = result.get("err_code_des", ErrorCode.NOT_PREPAY_ID[1])
                return False, (99999, err_code_des)
        else:
            return False, (99999, return_msg)

    except Exception as e:
        log_service.exception(e)

    log_service.info('PayResult ReturnCode:%s ReturnMSG:%s ResultCode:%s PrePayID:%s',
                     return_code, return_msg, result_code, prepay_id)

    if not prepay_id:
        return False, ErrorCode.NOT_PREPAY_ID
    ts_str = str(int(time.time()))
    _nonce_str = uuid.uuid1().hex.upper()
    app_sign_args = {
        'appid': WxConfig.WX_PAY_APP_ID_OFFICAL,  # 子商户在微信开放平台上申请的APPID
        'noncestr': _nonce_str,  # 随机字符串
        'package': 'Sign=WXPay',  # 扩展字段
        'partnerid': WxConfig.MCH_ID,  # 子商户的商户号
        "prepayid": prepay_id,  # 微信返回的支付交易会话ID
        'timestamp': ts_str,  # 时间戳
    }
    app_sign = calculate_signature(app_sign_args, WxConfig.WX_PAY_API_KEY)
    app_sign_args['sign'] = app_sign
    return True, app_sign_args


def wx_pay_notify(request):
    """订单微信支付回调"""
    return_code = "FAIL"
    log_service.info(request.data)
    try:
        notify_data = trans_xml_to_dict(request.data)
    except:
        return_msg = ErrorCode.FORMAT_ERROR_PAY_NOTIFY
        return trans_dict_to_xml({"return_code": return_code, "return_msg": return_msg})
    wx_sign = notify_data.pop("sign", "")
    app_sign = calculate_signature(notify_data, WxConfig.WX_PAY_API_KEY)
    if wx_sign != app_sign:
        return_msg = ErrorCode.BAD_SIGN
        return trans_dict_to_xml({"return_code": return_code, "return_msg": return_msg})
    if notify_data["return_code"] != "SUCCESS":
        return_msg = notify_data["err_code_des"]
        return trans_dict_to_xml({"return_code": return_code, "return_msg": return_msg})
    transaction_id = notify_data.get("transaction_id", "")  # 微信支付订单号
    out_trade_no = notify_data.get("out_trade_no", "")  # 商户订单号
    total_fee = notify_data.get("total_fee", "")  # 订单总金额,单位为分
    pay_time_str = notify_data.get("pay_time", "")  # 支付完成时间
    try:
        pay_time = datetime.datetime.strptime(pay_time_str, "%Y%m%d%H%M%S")
    except:
        pay_time = datetime.datetime.now()
    if not OrderPay.objects.filter(transaction_id=transaction_id).exists():
        main_order = MainOrder.objects.get(orderno=out_trade_no)
        data = {
            "main_order": main_order,
            "amount": Decimal(total_fee) / 100,
            "pay_time": pay_time,
            "pay_method": MainOrderPayMethod.wx,
            "confirm_time": datetime.datetime.now(),
            "status": OrderPayLogStatus.had_pay,
        }
        with transaction.atomic():
            order_pay = OrderPay.objects.create(**data)
            order_pay.gene_order_number()
            flow_main_order.update_main_order_paid_amount_status(main_order=main_order)  # 更新订单的支付金额和支付状态
    return_code = "SUCCESS"
    return_msg = "ok"
    return trans_dict_to_xml({"return_code": return_code, "return_msg": return_msg}

微信支付文档https://pay.weixin.qq.com/wiki/doc/api/app/app_sl.php?chapter=9_1

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 pythonista的日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档