|
|
# -*- coding: utf-8 -*-
|
|
|
import json
|
|
|
import logging
|
|
|
import os
|
|
|
from random import sample
|
|
|
from string import ascii_letters, digits
|
|
|
|
|
|
from flask import Flask, jsonify, request
|
|
|
|
|
|
from wechatpayv3 import SignType, WeChatPay, WeChatPayType
|
|
|
from flask_redis import FlaskRedis
|
|
|
import time
|
|
|
import uuid
|
|
|
|
|
|
# 微信支付商户号(直连模式)或服务商商户号(服务商模式,即sp_mchid)
|
|
|
MCHID = '123123123'
|
|
|
|
|
|
# 商户证书私钥
|
|
|
with open('./path_to_key/apiclient_key.pem') as f:
|
|
|
PRIVATE_KEY = f.read()
|
|
|
|
|
|
# 商户证书序列号
|
|
|
CERT_SERIAL_NO = '123123123'
|
|
|
|
|
|
# API v3密钥, https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
|
|
|
APIV3_KEY = '123123123'
|
|
|
|
|
|
# APPID,应用ID或服务商模式下的sp_appid
|
|
|
APPID = '123123123'
|
|
|
|
|
|
# 回调地址,也可以在调用接口的时候覆盖
|
|
|
NOTIFY_URL = ''
|
|
|
|
|
|
# 微信支付平台证书缓存目录,减少证书下载调用次数,首次使用确保此目录为空目录.
|
|
|
# 初始调试时可不设置,调试通过后再设置,示例值:'./cert'
|
|
|
CERT_DIR = None
|
|
|
|
|
|
# 日志记录器,记录web请求和回调细节
|
|
|
logging.basicConfig(filename=os.path.join(os.getcwd(), 'demo.log'), level=logging.DEBUG,
|
|
|
filemode='a', format='%(asctime)s - %(process)s - %(levelname)s: %(message)s')
|
|
|
LOGGER = logging.getLogger("demo")
|
|
|
|
|
|
# 接入模式:False=直连商户模式,True=服务商模式
|
|
|
PARTNER_MODE = False
|
|
|
|
|
|
# 代理设置,None或者{"https": "http://10.10.1.10:1080"},详细格式参见https://docs.python-requests.org/zh_CN/latest/user/advanced.html
|
|
|
PROXY = None
|
|
|
|
|
|
# 初始化
|
|
|
wxpay = WeChatPay(
|
|
|
wechatpay_type=WeChatPayType.JSAPI,
|
|
|
mchid=MCHID,
|
|
|
private_key=PRIVATE_KEY,
|
|
|
cert_serial_no=CERT_SERIAL_NO,
|
|
|
apiv3_key=APIV3_KEY,
|
|
|
appid=APPID,
|
|
|
notify_url=NOTIFY_URL,
|
|
|
cert_dir=CERT_DIR,
|
|
|
logger=LOGGER,
|
|
|
partner_mode=PARTNER_MODE,
|
|
|
proxy=PROXY)
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
|
|
|
@app.route('/game/wxcallback', methods=['POST'])
|
|
|
def wxcallback():
|
|
|
result = wxpay.callback(request.headers, request.data)
|
|
|
if result and result.get('event_type') == 'TRANSACTION.SUCCESS':
|
|
|
print("result = ", result)
|
|
|
resp = result.get('resource')
|
|
|
print("resp = ", resp)
|
|
|
print("out_trade_no = ", resp["out_trade_no"])
|
|
|
# appid = resp.get('appid')
|
|
|
# mchid = resp.get('mchid')
|
|
|
# out_trade_no = resp.get('out_trade_no')
|
|
|
# transaction_id = resp.get('transaction_id')
|
|
|
# trade_type = resp.get('trade_type')
|
|
|
# trade_state = resp.get('trade_state')
|
|
|
# trade_state_desc = resp.get('trade_state_desc')
|
|
|
# bank_type = resp.get('bank_type')
|
|
|
# attach = resp.get('attach')
|
|
|
# success_time = resp.get('success_time')
|
|
|
# payer = resp.get('payer')
|
|
|
# amount = resp.get('amount').get('total')
|
|
|
# TODO: 根据返回参数进行必要的业务处理,处理完后返回200或204
|
|
|
return jsonify({'code': 'SUCCESS', 'message': '成功', 'data': resp})
|
|
|
else:
|
|
|
return jsonify({'code': 'FAILED', 'message': '失败'})
|
|
|
|
|
|
|
|
|
@app.route('/game/h5pay', methods=['POST'])
|
|
|
def h5pay():
|
|
|
body = request.get_json()
|
|
|
print("body = ", body)
|
|
|
code, resp_str = wxpay.pay(description=body["description"],
|
|
|
out_trade_no=body["order_no"],
|
|
|
amount={'total': int(body["payment"])},
|
|
|
payer={'openid': body["openid"]},
|
|
|
pay_type=WeChatPayType.JSAPI)
|
|
|
if code == 200:
|
|
|
resp = json.loads(resp_str)
|
|
|
prepay_id = resp["prepay_id"]
|
|
|
timestamp = int(time.time())
|
|
|
nonceStr = "".join(str(uuid.uuid4()).split('-')).upper()
|
|
|
package = f"prepay_id={prepay_id}"
|
|
|
data = [APPID, str(timestamp), nonceStr, package]
|
|
|
paySign = wxpay.sign(data)
|
|
|
resp["timestamp"] = str(timestamp)
|
|
|
resp["nonceStr"] = nonceStr
|
|
|
resp["prepay_id"] = prepay_id
|
|
|
resp["package"] = package
|
|
|
resp["paySign"] = paySign
|
|
|
return jsonify({'code': code, 'data': resp})
|
|
|
return jsonify({'code': code})
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
app.run()
|