Python實現支付寶在線支付

 

windows系統安裝Python虛擬環境python

首先保證你的系統已經安裝好了Pythonmysql

安裝virtualenvreact

C:\WINDOWS\system32>pip3 install virtualenv
Collecting virtualenv
  Downloading virtualenv-15.1.0-py2.py3-none-any.whl (1.8MB)
    100% |████████████████████████████████| 1.8MB 110kB/s
Installing collected packages: virtualenv
Successfully installed virtualenv-15.1.0

C:\WINDOWS\system32>

安裝virtualenvwrappersql

virtualenvwrapper是virtualenv的一個方便管理虛擬環境的管理器數據庫

pip3 install virtualenvwrapper

 

指定虛擬環境,保存路徑django

首先在要保存虛擬環境的地方建立一個Evns目錄,而後將這個目錄添加到系統環境變量,之後建立的虛擬環境就會保存在這個目錄,重啓系統後生效json

 

建立虛擬環境,建立後會自動進入虛擬環境vim

mkvirtualenv 虛擬環境名稱windows

[root@192 xu_ni_huan_jing]# mkvirtualenv jxiou
Using base prefix '/usr/local'
New python executable in /usr/xu_ni_huan_jing/jxiou/bin/python3.5
Also creating executable in /usr/xu_ni_huan_jing/jxiou/bin/python
Installing setuptools, pip, wheel...done.
virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/predeactivate
virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/postdeactivate
virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/preactivate
virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/postactivate
virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/get_env_details
(jxiou) [root@192 xu_ni_huan_jing]# 

 

5.退出虛擬環境api

deactivate

(jxiou) [root@192 xu_ni_huan_jing]# deactivate
[root@192 xu_ni_huan_jing]# 

 

6.查看有哪些虛擬環境

workon

[root@192 /]# workon
jxiou2
jxiou
[root@192 /]# 

 

7.進入一個指定的虛擬環境

workon jxiou(虛擬環境名稱)

[root@192 /]# workon jxiou
(jxiou) [root@192 /]#

 

8.虛擬環境建立好後,建立Django項目,建立好數據庫,開始本地調試支付請求

 

支付寶接口集成 ,本地環境調試支付請求

1。首先登陸 螞蟻金服網站,也就是支付寶開發者平臺

登陸螞蟻金服開發者平臺後,建立沙箱應用

 

也就是支付寶給開發者提供的調試環境應用

 

注意這裏咱們必定選擇RSA2(SHA256)密鑰(推薦),這個是比較安全的方式,

 

2.咱們設置應用公鑰

設置公鑰,訪問https://docs.open.alipay.com/291/105971/ 這個網址

下載生成公鑰的工具

 

下載解壓後

生成公鑰

生成公鑰後會獲得兩個文件

注意:這兩個文件很重要必定要保存好

 

生成公鑰後,將公鑰填寫到信息配置裏

 

 

當咱們填寫好公鑰保存後,會自動給咱們生成支付寶公鑰

 

生成的支付寶公鑰,複製下載寫在一個TXT文件裏

這樣咱們就有了3個祕鑰

 將3個祕鑰修改爲英文或者拼音名稱後,放到網站項目中

 

在祕鑰txt文件裏,祕鑰內容的頭部和結尾加上兩行字符串,注意全部祕鑰都要加

 

-----BEGIN PRIVATE KEY-----
祕鑰內容....
-----END PRIVATE KEY-----

 

3.支付寶,支付集成代碼

#!/usr/bin/env python
# -*- coding:utf8 -*-

# pip install pycryptodome   須要模塊加密方面的模塊
__author__ = 'bobby'

from datetime import datetime
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64encode, b64decode
from urllib.parse import quote_plus
from urllib.parse import urlparse, parse_qs
from urllib.request import urlopen
from base64 import decodebytes, encodebytes

import json


class AliPay(object):
    """
    支付寶支付接口
    """
    def __init__(self, appid, app_notify_url, app_private_key_path,
                 alipay_public_key_path, return_url, debug=False):
        self.appid = appid
        self.app_notify_url = app_notify_url
        self.app_private_key_path = app_private_key_path
        self.app_private_key = None
        self.return_url = return_url
        with open(self.app_private_key_path) as fp:
            self.app_private_key = RSA.importKey(fp.read())

        self.alipay_public_key_path = alipay_public_key_path
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.import_key(fp.read())


        if debug is True:
            self.__gateway = "https://openapi.alipaydev.com/gateway.do"
        else:
            self.__gateway = "https://openapi.alipay.com/gateway.do"

    def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
        biz_content = {
            "subject": subject,
            "out_trade_no": out_trade_no,
            "total_amount": total_amount,
            "product_code": "FAST_INSTANT_TRADE_PAY",
            # "qr_pay_mode":4
        }

        biz_content.update(kwargs)
        data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
        return self.sign_data(data)

    def build_body(self, method, biz_content, return_url=None):
        data = {
            "app_id": self.appid,
            "method": method,
            "charset": "utf-8",
            "sign_type": "RSA2",
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "version": "1.0",
            "biz_content": biz_content
        }

        if return_url is not None:
            data["notify_url"] = self.app_notify_url
            data["return_url"] = self.return_url

        return data

    def sign_data(self, data):
        data.pop("sign", None)
        # 排序後的字符串
        unsigned_items = self.ordered_data(data)
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        sign = self.sign(unsigned_string.encode("utf-8"))
        ordered_items = self.ordered_data(data)
        quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in ordered_items)

        # 得到最終的訂單信息字符串
        signed_string = quoted_string + "&sign=" + quote_plus(sign)
        return signed_string

    def ordered_data(self, data):
        complex_keys = []
        for key, value in data.items():
            if isinstance(value, dict):
                complex_keys.append(key)

        # 將字典類型的數據dump出來
        for key in complex_keys:
            data[key] = json.dumps(data[key], separators=(',', ':'))

        return sorted([(k, v) for k, v in data.items()])

    def sign(self, unsigned_string):
        # 開始計算簽名
        key = self.app_private_key
        signer = PKCS1_v1_5.new(key)
        signature = signer.sign(SHA256.new(unsigned_string))
        # base64 編碼,轉換爲unicode表示並移除回車
        sign = encodebytes(signature).decode("utf8").replace("\n", "")
        return sign

    def _verify(self, raw_content, signature):
        # 開始計算簽名
        key = self.alipay_public_key
        signer = PKCS1_v1_5.new(key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        if signer.verify(digest, decodebytes(signature.encode("utf8"))):
            return True
        return False

    def verify(self, data, signature):
        if "sign_type" in data:
            sign_type = data.pop("sign_type")
        # 排序後的字符串
        unsigned_items = self.ordered_data(data)
        message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
        return self._verify(message, signature)


if __name__ == "__main__": """支付請求過程"""
    # 傳遞參數初始化支付類
    alipay = AliPay( appid="2016080800192023",                                   # 設置簽約的appid
        app_notify_url="http://projectsedus.com/",                  # 異步支付通知url
        app_private_key_path=u"ying_yong_si_yao.txt",               # 設置應用私鑰
        alipay_public_key_path="zhi_fu_bao_gong_yao.txt",           # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰,
        debug=True,  # 默認False, # 設置是不是沙箱環境,True是沙箱環境
        return_url="http://47.92.87.172:8000/"                      # 同步支付通知url
 ) # 傳遞參數執行支付類裏的direct_pay方法,返回簽名後的支付參數,
    url = alipay.direct_pay( subject="測試訂單",                              # 訂單名稱
        # 訂單號生成,通常是當前時間(精確到秒)+用戶ID+隨機數
        out_trade_no="201702021225",                    # 訂單號
        total_amount=100,                               # 支付金額
        return_url="http://47.92.87.172:8000/"          # 支付成功後,跳轉url
 ) # 將前面後的支付參數,拼接到支付網關
    # 注意:下面支付網關是沙箱環境,
    re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url) print(re_url) # 最終進行簽名後組合成支付寶的url請求

 

4.生成支付URL後,咱們用這個URL模擬支付一下

注意:沙箱環境,支付的時候要用沙箱帳號裏提供的支付帳號才能夠支付

 

支付成功後已經,跳轉到咱們設置的同步處理頁面

 

 

5.支付寶支付成功後通知接口驗證

#!/usr/bin/env python
# -*- coding:utf8 -*-

# pip install pycryptodome   須要模塊加密方面的模塊
__author__ = 'bobby'

from datetime import datetime
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64encode, b64decode
from urllib.parse import quote_plus
from urllib.parse import urlparse, parse_qs
from urllib.request import urlopen
from base64 import decodebytes, encodebytes

import json


class AliPay(object):
    """
    支付寶支付接口
    """
    def __init__(self, appid, app_notify_url, app_private_key_path,
                 alipay_public_key_path, return_url, debug=False):
        self.appid = appid
        self.app_notify_url = app_notify_url
        self.app_private_key_path = app_private_key_path
        self.app_private_key = None
        self.return_url = return_url
        with open(self.app_private_key_path) as fp:
            self.app_private_key = RSA.importKey(fp.read())

        self.alipay_public_key_path = alipay_public_key_path
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.import_key(fp.read())


        if debug is True:
            self.__gateway = "https://openapi.alipaydev.com/gateway.do"
        else:
            self.__gateway = "https://openapi.alipay.com/gateway.do"

    def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
        biz_content = {
            "subject": subject,
            "out_trade_no": out_trade_no,
            "total_amount": total_amount,
            "product_code": "FAST_INSTANT_TRADE_PAY",
            # "qr_pay_mode":4
        }

        biz_content.update(kwargs)
        data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
        return self.sign_data(data)

    def build_body(self, method, biz_content, return_url=None):
        data = {
            "app_id": self.appid,
            "method": method,
            "charset": "utf-8",
            "sign_type": "RSA2",
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "version": "1.0",
            "biz_content": biz_content
        }

        if return_url is not None:
            data["notify_url"] = self.app_notify_url
            data["return_url"] = self.return_url

        return data

    def sign_data(self, data):
        data.pop("sign", None)
        # 排序後的字符串
        unsigned_items = self.ordered_data(data)
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        sign = self.sign(unsigned_string.encode("utf-8"))
        ordered_items = self.ordered_data(data)
        quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in ordered_items)

        # 得到最終的訂單信息字符串
        signed_string = quoted_string + "&sign=" + quote_plus(sign)
        return signed_string

    def ordered_data(self, data):
        complex_keys = []
        for key, value in data.items():
            if isinstance(value, dict):
                complex_keys.append(key)

        # 將字典類型的數據dump出來
        for key in complex_keys:
            data[key] = json.dumps(data[key], separators=(',', ':'))

        return sorted([(k, v) for k, v in data.items()])

    def sign(self, unsigned_string):
        # 開始計算簽名
        key = self.app_private_key
        signer = PKCS1_v1_5.new(key)
        signature = signer.sign(SHA256.new(unsigned_string))
        # base64 編碼,轉換爲unicode表示並移除回車
        sign = encodebytes(signature).decode("utf8").replace("\n", "")
        return sign

    def _verify(self, raw_content, signature):
        # 開始計算簽名
        key = self.alipay_public_key
        signer = PKCS1_v1_5.new(key)
        digest = SHA256.new()
        digest.update(raw_content.encode("utf8"))
        if signer.verify(digest, decodebytes(signature.encode("utf8"))):
            return True
        return False

    def verify(self, data, signature):
        if "sign_type" in data:
            sign_type = data.pop("sign_type")
        # 排序後的字符串
        unsigned_items = self.ordered_data(data)
        message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
        return self._verify(message, signature)


if __name__ == "__main__": """支付寶支付成功後通知接口驗證"""

    # 接收支付寶支付成功後,向咱們設置的同步支付通知url,請求的參數
    return_url = 'http://47.92.87.172:8000/?total_amount=100.00&timestamp=2017-10-11+22%3A44%3A17&sign=dHW%2F25EDd%2BYKqkU5krhseDNIOEyDpdJzSAaoqhTC0nlv8%2FEmrQVd0WqgGK0CS8Pax8sK4jIOdGLFa6lQEbIfzvH3Na2W949yCAYX04JL1Bi02wog7a8L7vfW9Kj%2BjfTQxumGH%2B1Drbezdg9gKOx3tX0cb1yBBdfifK6l1%2BE5UjggGbY60F6SD8A8XI06NMWb4ViU%2FLYtBhwAwU2koy1IK2%2BtBJM1xYFuBRlcWF61xCxexHwO0WEA3AwVRW1miuJjOpGiBTOwPI9Huj0WhkyRebIjBhSxReJdZIdTfAgwj4oqo4jAJCHDa6DKBM0H3wjKKXSyMeMBGKQB0Uv2rNdyng%3D%3D&trade_no=2017101121001004320200174640&sign_type=RSA2&auth_app_id=2016080800192023&charset=utf-8&seller_id=2088102170418468&method=alipay.trade.page.pay.return&app_id=2016080800192023&out_trade_no=201702021227&version=1.0'

    # 將同步支付通知url,傳到urlparse
    o = urlparse(return_url) # 獲取到URL的各類參數
    query = parse_qs(o.query) # 定義一個字典來存放,循環獲取到的URL參數
    processed_query = {} # 將URL參數裏的sign字段拿出來
    ali_sign = query.pop("sign")[0] # 傳遞參數初始化支付類
    alipay = AliPay( appid="2016080800192023",                                   # 設置簽約的appid
        app_notify_url="http://projectsedus.com/",                  # 異步支付通知url
        app_private_key_path=u"ying_yong_si_yao.txt",               # 設置應用私鑰
        alipay_public_key_path="zhi_fu_bao_gong_yao.txt",           # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰,
        debug=True,  # 默認False, # 設置是不是沙箱環境,True是沙箱環境
        return_url="http://47.92.87.172:8000/"                      # 同步支付通知url
 ) # 循環出URL裏的參數
    for key, value in query.items(): # 將循環到的參數,以鍵值對形式追加到processed_query字典
        processed_query[key] = value[0] # 將循環組合的參數字典,以及拿出來的sign字段,傳進支付類裏的verify方法,返回驗證合法性,返回布爾值,True爲合法,表示支付確實成功了,這就是驗證是不是僞造支付成功請求
    print(alipay.verify(processed_query, ali_sign)) # 若是別人僞造支付成功請求,它不知道咱們的支付寶公鑰,僞造的就沒法經過驗證,測試能夠將支付寶公鑰更改一下,在驗證就會失敗,別忘了改回來

 

 

遠程測試支付成功後返回服務器驗證

首先準備一臺服務器,將開發環境和項目同步到服務器上,而且在服務器上配置好python虛擬環境和所需python插件包

 

項目同步到服務器上,也就是將本地項目,上傳到服務器進行同步

配置服務器信息

2

上傳項目

數據上傳後,在服務器配置數據庫訪問權限,和配置python環境

 

配置遠程調試

1,在阿里雲後臺,開放8000端口

 

2,在服務器開發8000端口

vim /etc/sysconfig/iptables
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
#添加配置項
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8000 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

重啓防火牆

service iptables restart

 

設置當前,使用的數據庫用戶,能夠任意ip訪問

讓數據庫用戶能夠從外部登錄和本地登錄

1

grant all privileges(除受權外的全部權限) on *.*(表示全部數據庫的全部表) to 'test_user(受權的用戶名)'@'localhost(受權ip)' identified by 'test_user(用戶密碼)';

grant all privileges on *.* to 'test_user'@'localhost' identified by 'test_user';

2

grant all privileges(除受權外的全部權限) on *.*(表示全部數據庫的全部表) to 'test_user(受權的用戶名)'@'%(全部ip)' identified by 'test_user(用戶密碼)';
grant all privileges on *.* to 'test_user'@'%' identified by 'test_user';

 

配置項目的settings.py文件

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',       #配置數據庫引擎名稱
        'NAME': 'jxiou',                            #數據庫名稱
        'USER': 'test_user',                             #數據庫用戶名
        'PASSWORD': 'test_user',                       #數據庫密碼
        'HOST': '47.52.39.160',                        #數據庫連接地址,爲服務器ip
        'PORT': '3306',                             #數據庫端口
    }
}

2

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']   # 容許任意ip訪問項目

 

開始遠程調試

2

3

4

5

此時,就能夠用服務器ip加8000端口,訪問服務器網站了

前面,咱們在本地調試了支付寶支付請求,這下咱們要調試,支付寶支付成功後向咱們服務器返回請求咱們要驗證返回的請求,,因此須要將遠程服務器啓動來,接收支付寶的返回

settings.py

 

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 支付寶目錄路徑設置
ying_yong_si_yao = os.path.join(BASE_DIR, 'app1/alipay/ying_yong_si_yao.txt') zhi_fu_bao_gong_yao = os.path.join(BASE_DIR, 'app1/alipay/zhi_fu_bao_gong_yao.txt')

 

 

 

 

urls.py

 

from django.conf.urls import url
from django.contrib import admin
from app1.views import alipaview

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 支付寶返回url
    url(r'^alipa/', alipaview, name='alipa'),
]

 

 

views.py

#!/usr/bin/env python
# -*- coding:utf8 -*-
from django.shortcuts import render

# Create your views here.
from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt,csrf_protect from app1.alipay.alipay import AliPay from jxiou.settings import ying_yong_si_yao, zhi_fu_bao_gong_yao

@csrf_exempt def alipaview(request):
    if request.method == "GET": processed_dict = {}  # 接收支付寶傳遞參數
        for key, value in request.GET.items():  # 循環參數
            processed_dict[key] = value  # 將參數添加到字典
        sign = processed_dict.pop('sign', None)  # 單獨拿出sign字段

        # 傳遞參數初始化支付類
        alipay = AliPay( appid="2016080800192023",  # 設置簽約的appid
            app_notify_url="http://47.52.39.160:8000/alipa/",  # 異步支付通知url
            app_private_key_path=ying_yong_si_yao,  # 設置應用私鑰
            alipay_public_key_path=zhi_fu_bao_gong_yao,  # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰,
            debug=True,  # 默認False, # 設置是不是沙箱環境,True是沙箱環境
            return_url="http://47.52.39.160:8000/alipa/"  # 同步支付通知url,跳轉地址
 ) # 驗證支付寶返回的合法性
        yan_zhen = alipay.verify(processed_dict, sign) if yan_zhen is True:  # 判斷若是合法
            out_trade_no = processed_dict.get('out_trade_no', None)  # 商戶訂單號
            trade_no = processed_dict.get('trade_no', None)  # 支付寶交易號
            buyer_id = processed_dict.get('buyer_id', None)  # 買家支付寶用戶號
            trade_status = processed_dict.get('trade_status', None)  # 交易狀態
            total_amount = processed_dict.get('total_amount', None)  # 訂單金額
            receipt_amount = processed_dict.get('receipt_amount', None)  # 實收金額
            subject = processed_dict.get('subject', None)  # 訂單標題
            gmt_payment = processed_dict.get('gmt_payment', None)  # 交易付款時間

            # 數據庫操做
            print(out_trade_no) print(trade_no) print(buyer_id) print(trade_status) print(total_amount) print(receipt_amount) print(subject) print(gmt_payment) # 向支付寶返回success,告訴他咱們已經處理,否則他會不停的通知
            return HttpResponse('success') if request.method == "POST":                        # post請求支付寶異步通知
        processed_dict = {}                             # 接收支付寶傳遞參數
        for key, value in request.POST.items():         # 循環參數
            processed_dict[key] = value                 # 將參數添加到字典
        sign = processed_dict.pop('sign', None)         # 單獨拿出sign字段

        # 傳遞參數初始化支付類
        alipay = AliPay( appid="2016080800192023",                                   # 設置簽約的appid
            app_notify_url="http://47.52.39.160:8000/alipa/",           # 異步支付通知url
            app_private_key_path=ying_yong_si_yao,                      # 設置應用私鑰
            alipay_public_key_path=zhi_fu_bao_gong_yao,                 # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰,
            debug=True,  # 默認False, # 設置是不是沙箱環境,True是沙箱環境
            return_url="http://47.52.39.160:8000/alipa/"                # 同步支付通知url
 ) # 驗證支付寶返回的合法性
        yan_zhen = alipay.verify(processed_dict, sign) if yan_zhen is True:                                                # 判斷若是合法
            out_trade_no = processed_dict.get('out_trade_no', None)         # 商戶訂單號
            trade_no = processed_dict.get('trade_no', None)                 # 支付寶交易號
            buyer_id = processed_dict.get('buyer_id', None)                 # 買家支付寶用戶號
            trade_status = processed_dict.get('trade_status', None)         # 交易狀態
            total_amount = processed_dict.get('total_amount', None)         # 訂單金額
            receipt_amount = processed_dict.get('receipt_amount', None)     # 實收金額
            subject = processed_dict.get('subject', None)                   # 訂單標題
            gmt_payment = processed_dict.get('gmt_payment', None)           # 交易付款時間

            # 數據庫操做
            print(out_trade_no) print(trade_no) print(buyer_id) print(trade_status) print(total_amount) print(receipt_amount) print(subject) print(gmt_payment) # 向支付寶返回success,告訴他咱們已經處理,否則他會不停的通知
            return HttpResponse('success')

 

WAIT_BUYER_PAY 交易建立,等待買家付款TRADE_CLOSED 未付款交易超時關閉,或支付完成後全額退款TRADE_SUCCESS 交易支付成功TRADE_FINISHED 交易結束,不可退款

相關文章
相關標籤/搜索