diff --git a/backend/internal/integrations/payment/leshua/client.go b/backend/internal/integrations/payment/leshua/client.go
index 26781eb..7763aa9 100644
--- a/backend/internal/integrations/payment/leshua/client.go
+++ b/backend/internal/integrations/payment/leshua/client.go
@@ -77,6 +77,7 @@ type VerifyNotifyResult struct {
MatchedKey string
Got string
Expected map[string]string
+ BaseString map[string]string
ParamKeys []string
}
@@ -185,19 +186,19 @@ func (c *Client) VerifyNotify(params map[string]string) bool {
func (c *Client) VerifyNotifyDetail(params map[string]string) VerifyNotifyResult {
got := strings.ToUpper(params["sign"])
result := VerifyNotifyResult{
- Got: got,
- Expected: map[string]string{},
- ParamKeys: notifyParamKeys(params),
+ Got: got,
+ Expected: map[string]string{},
+ BaseString: map[string]string{},
+ ParamKeys: notifyParamKeys(params),
}
if got == "" {
return result
}
for _, item := range c.notifyKeyCandidates() {
- expected := Sign(params, item.key, SignOptions{
- IncludeEmpty: true,
- ExcludeKeys: []string{"error_code", "sign"},
- })
+ expected := Sign(params, item.key, notifySignOptions())
+ baseString := SignBaseString(params, notifySignOptions())
result.Expected[item.name] = expected
+ result.BaseString[item.name] = baseString
if got == expected {
result.OK = true
result.MatchedKey = item.name
@@ -207,6 +208,13 @@ func (c *Client) VerifyNotifyDetail(params map[string]string) VerifyNotifyResult
return result
}
+func notifySignOptions() SignOptions {
+ return SignOptions{
+ IncludeEmpty: true,
+ ExcludeKeys: []string{"error_code", "leshua", "sign"},
+ }
+}
+
type notifyKeyCandidate struct {
name string
key string
@@ -217,16 +225,13 @@ func (c *Client) notifyKeyCandidates() []notifyKeyCandidate {
if c.cfg.NotifyKey != "" {
candidates = append(candidates, notifyKeyCandidate{name: "notify_key", key: c.cfg.NotifyKey})
}
- if c.cfg.SignKey != "" && c.cfg.SignKey != c.cfg.NotifyKey {
- candidates = append(candidates, notifyKeyCandidate{name: "sign_key", key: c.cfg.SignKey})
- }
return candidates
}
func notifyParamKeys(params map[string]string) []string {
keys := make([]string, 0, len(params))
for key := range params {
- if key == "sign" || key == "error_code" {
+ if key == "sign" || key == "error_code" || key == "leshua" {
continue
}
keys = append(keys, key)
@@ -276,6 +281,16 @@ type SignOptions struct {
}
func Sign(params map[string]string, key string, opts SignOptions) string {
+ baseString := SignBaseString(params, opts)
+ stringSignTemp := "key=" + key
+ if baseString != "" {
+ stringSignTemp = baseString + "&key=" + key
+ }
+ sum := md5.Sum([]byte(stringSignTemp))
+ return strings.ToUpper(hex.EncodeToString(sum[:]))
+}
+
+func SignBaseString(params map[string]string, opts SignOptions) string {
excluded := map[string]bool{}
for _, item := range opts.ExcludeKeys {
excluded[item] = true
@@ -298,9 +313,7 @@ func Sign(params map[string]string, key string, opts SignOptions) string {
for _, name := range keys {
parts = append(parts, name+"="+params[name])
}
- parts = append(parts, "key="+key)
- sum := md5.Sum([]byte(strings.Join(parts, "&")))
- return strings.ToUpper(hex.EncodeToString(sum[:]))
+ return strings.Join(parts, "&")
}
func ParsePayload(body []byte) (map[string]string, error) {
@@ -342,6 +355,7 @@ func parseXMLPayload(body []byte) (map[string]string, error) {
decoder := xml.NewDecoder(bytes.NewReader(body))
out := map[string]string{}
var current string
+ depth := 0
for {
token, err := decoder.Token()
if err == io.EOF {
@@ -352,14 +366,25 @@ func parseXMLPayload(body []byte) (map[string]string, error) {
}
switch item := token.(type) {
case xml.StartElement:
- current = item.Name.Local
+ depth++
+ if depth > 1 {
+ current = item.Name.Local
+ if _, exists := out[current]; !exists {
+ out[current] = ""
+ }
+ }
case xml.CharData:
value := strings.TrimSpace(string(item))
- if current != "" && current != "xml" && value != "" {
+ if current != "" && value != "" {
out[current] = value
}
case xml.EndElement:
- current = ""
+ if current == item.Name.Local {
+ current = ""
+ }
+ if depth > 0 {
+ depth--
+ }
}
}
return out, nil
diff --git a/backend/internal/integrations/payment/leshua/client_test.go b/backend/internal/integrations/payment/leshua/client_test.go
index 22b0f1d..72f9a87 100644
--- a/backend/internal/integrations/payment/leshua/client_test.go
+++ b/backend/internal/integrations/payment/leshua/client_test.go
@@ -1,6 +1,7 @@
package leshua
import (
+ "strings"
"testing"
"hfb_sys/backend/internal/config"
@@ -22,6 +23,12 @@ func TestSignUsesASCIISortedNonEmptyParams(t *testing.T) {
if got != want {
t.Fatalf("Sign() = %s, want %s", got, want)
}
+
+ baseString := SignBaseString(params, SignOptions{})
+ wantBaseString := "amount=100&merchant_id=1234567890&nonce_str=abc&service=get_tdcode&third_order_id=NO1"
+ if baseString != wantBaseString {
+ t.Fatalf("SignBaseString() = %s, want %s", baseString, wantBaseString)
+ }
}
func TestVerifyNotifyIncludesEmptyAndExcludesErrorCode(t *testing.T) {
@@ -33,11 +40,12 @@ func TestVerifyNotifyIncludesEmptyAndExcludesErrorCode(t *testing.T) {
"amount": "100",
"status": "2",
"attach": "",
+ "leshua": "",
"error_code": "-20001",
}
params["sign"] = Sign(params, "notify-secret", SignOptions{
IncludeEmpty: true,
- ExcludeKeys: []string{"error_code", "sign"},
+ ExcludeKeys: []string{"error_code", "leshua", "sign"},
})
if !client.VerifyNotify(params) {
@@ -50,7 +58,7 @@ func TestVerifyNotifyIncludesEmptyAndExcludesErrorCode(t *testing.T) {
}
}
-func TestVerifyNotifyFallsBackToSignKey(t *testing.T) {
+func TestVerifyNotifyDoesNotFallBackToSignKey(t *testing.T) {
client := NewClient(config.LeshuaPaymentConfig{
NotifyKey: "wrong-notify-secret",
SignKey: "sign-secret",
@@ -67,12 +75,64 @@ func TestVerifyNotifyFallsBackToSignKey(t *testing.T) {
ExcludeKeys: []string{"error_code", "sign"},
})
+ result := client.VerifyNotifyDetail(params)
+ if result.OK {
+ t.Fatal("VerifyNotifyDetail().OK = true, want false")
+ }
+ if _, ok := result.Expected["sign_key"]; ok {
+ t.Fatal("VerifyNotifyDetail() unexpectedly used sign_key fallback")
+ }
+}
+
+func TestVerifyNotifyUsesDocumentedNotifySignature(t *testing.T) {
+ client := NewClient(config.LeshuaPaymentConfig{NotifyKey: "notify-secret"})
+ params := map[string]string{
+ "merchant_id": "1234567890",
+ "third_order_id": "NO1",
+ "leshua_order_id": "LS1",
+ "amount": "100",
+ "status": "2",
+ "sign_type": "MD5",
+ }
+ params["sign"] = Sign(params, "notify-secret", SignOptions{
+ IncludeEmpty: true,
+ ExcludeKeys: []string{"error_code", "leshua", "sign"},
+ })
+
result := client.VerifyNotifyDetail(params)
if !result.OK {
t.Fatal("VerifyNotifyDetail().OK = false, want true")
}
- if result.MatchedKey != "sign_key" {
- t.Fatalf("MatchedKey = %s, want sign_key", result.MatchedKey)
+ if result.MatchedKey != "notify_key" {
+ t.Fatalf("MatchedKey = %s, want notify_key", result.MatchedKey)
+ }
+}
+
+func TestVerifyNotifyKeepsEmptyXMLFieldsInSignature(t *testing.T) {
+ client := NewClient(config.LeshuaPaymentConfig{NotifyKey: "notify-secret"})
+ params, err := ParsePayload([]byte(`
+100
+
+1234567890
+MD5
+2
+NO1
+`))
+ if err != nil {
+ t.Fatalf("ParsePayload(xml) error = %v", err)
+ }
+ params["sign"] = Sign(params, "notify-secret", SignOptions{
+ IncludeEmpty: true,
+ ExcludeKeys: []string{"error_code", "leshua", "sign"},
+ })
+
+ result := client.VerifyNotifyDetail(params)
+ if !result.OK {
+ t.Fatal("VerifyNotifyDetail().OK = false, want true")
+ }
+ baseString := result.BaseString[result.MatchedKey]
+ if !strings.Contains(baseString, "goods_tag=") {
+ t.Fatalf("baseString = %s, want goods_tag included", baseString)
}
}
@@ -85,11 +145,17 @@ func TestParsePayloadSupportsFormAndXML(t *testing.T) {
t.Fatalf("ParsePayload(form) = %#v", form)
}
- xml, err := ParsePayload([]byte("NO26"))
+ xml, err := ParsePayload([]byte("NO26"))
if err != nil {
t.Fatalf("ParsePayload(xml) error = %v", err)
}
if xml["third_order_id"] != "NO2" || xml["status"] != "6" {
t.Fatalf("ParsePayload(xml) = %#v", xml)
}
+ if value, ok := xml["goods_tag"]; !ok || value != "" {
+ t.Fatalf("ParsePayload(xml).goods_tag = %q, exists=%v; want empty value", value, ok)
+ }
+ if value, ok := xml["coupon"]; !ok || value != "" {
+ t.Fatalf("ParsePayload(xml).coupon = %q, exists=%v; want empty value", value, ok)
+ }
}
diff --git a/backend/internal/modules/payment/handler.go b/backend/internal/modules/payment/handler.go
index a91d0ac..2ea0be0 100644
--- a/backend/internal/modules/payment/handler.go
+++ b/backend/internal/modules/payment/handler.go
@@ -110,8 +110,18 @@ func (h *Handler) LeshuaNotify(c *gin.Context) {
c.String(http.StatusBadRequest, "FAIL")
return
}
- log.Printf("[payment] leshua notify received third_order_id=%s leshua_order_id=%s status=%s amount=%s", params["third_order_id"], params["leshua_order_id"], params["status"], params["amount"])
- result, err := h.service.HandleLeshuaNotify(params)
+ rawPayload := string(body)
+ contentType := c.GetHeader("Content-Type")
+ log.Printf(
+ "[payment] leshua notify received third_order_id=%s leshua_order_id=%s status=%s amount=%s content_type=%s raw_payload=%s",
+ params["third_order_id"],
+ params["leshua_order_id"],
+ params["status"],
+ params["amount"],
+ contentType,
+ rawPayload,
+ )
+ result, err := h.service.HandleLeshuaNotify(params, rawPayload, contentType)
if err != nil || result == nil || !result.OK {
log.Printf("[payment] leshua notify failed third_order_id=%s err=%v", params["third_order_id"], err)
c.String(http.StatusOK, "FAIL")
diff --git a/backend/internal/modules/payment/repository.go b/backend/internal/modules/payment/repository.go
index 2bc12ae..078500a 100644
--- a/backend/internal/modules/payment/repository.go
+++ b/backend/internal/modules/payment/repository.go
@@ -125,7 +125,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
amountCent := moneyCent(req.Amount)
- if userID == 0 || amountCent <= 0 {
+ if userID == 0 || req.Amount < MinWalletRechargeAmount || amountCent <= 0 {
return nil, ErrPaymentCannotStart
}
payment, err := r.createWalletRechargePayment(userID, amountCent, req)
@@ -241,17 +241,22 @@ func (r *Repository) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
return &dto, nil
}
-func (r *Repository) HandleLeshuaNotify(params map[string]string) (*NotifyResult, error) {
+func (r *Repository) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
+ var verify leshua.VerifyNotifyResult
if !r.isMockMode {
- verify := r.leshua.VerifyNotifyDetail(params)
+ verify = r.leshua.VerifyNotifyDetail(params)
if !verify.OK {
log.Printf(
- "[payment] leshua notify verify failed third_order_id=%s got=%s expected=%v keys=%v",
+ "[payment] leshua notify verify failed third_order_id=%s got=%s expected=%s keys=%v base_string=%s",
params["third_order_id"],
- shortSign(verify.Got),
- shortExpectedSigns(verify.Expected),
+ verify.Got,
+ verify.Expected["notify_key"],
verify.ParamKeys,
+ verify.BaseString["notify_key"],
)
+ if err := r.recordNotifyDiagnostic(params, rawPayload, contentType, verify, "verify_failed"); err != nil {
+ log.Printf("[payment] leshua notify diagnostic save failed third_order_id=%s err=%v", params["third_order_id"], err)
+ }
return nil, ErrPaymentVerifyFailed
}
log.Printf("[payment] leshua notify verified third_order_id=%s matched_key=%s", params["third_order_id"], verify.MatchedKey)
@@ -268,9 +273,13 @@ func (r *Repository) HandleLeshuaNotify(params map[string]string) (*NotifyResult
return nil, err
}
if amount := parseCent(params["amount"]); amount > 0 && amount != payment.AmountCent {
+ if err := r.recordNotifyDiagnostic(params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
+ log.Printf("[payment] leshua notify diagnostic save failed third_order_id=%s err=%v", params["third_order_id"], err)
+ }
return nil, ErrPaymentVerifyFailed
}
- if err := r.applyChannelStatus(&payment, params["status"], params["pay_time"], params, channelSourceNotify); err != nil {
+ raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, "verified")
+ if err := r.applyChannelStatus(&payment, params["status"], params["pay_time"], raw, channelSourceNotify); err != nil {
return nil, err
}
return &NotifyResult{OK: true, Message: "000000"}, nil
@@ -531,6 +540,40 @@ func withRawSource(raw map[string]string, source string) map[string]string {
return out
}
+func (r *Repository) recordNotifyDiagnostic(params map[string]string, rawPayload string, contentType string, verify leshua.VerifyNotifyResult, status string) error {
+ thirdOrderID := params["third_order_id"]
+ if thirdOrderID == "" {
+ return nil
+ }
+ raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, status)
+ return r.db.Model(&model.PaymentOrder{}).
+ Where("third_order_id = ?", thirdOrderID).
+ Update("raw_response", jsonMap(raw)).Error
+}
+
+func withNotifyDiagnostic(params map[string]string, rawPayload string, contentType string, verify leshua.VerifyNotifyResult, status string) map[string]string {
+ raw := withRawSource(params, channelSourceNotify)
+ raw["_notify_diagnostic_status"] = status
+ raw["_raw_payload"] = rawPayload
+ raw["_raw_content_type"] = contentType
+ raw["_sign_got"] = verify.Got
+ raw["_sign_matched_key"] = verify.MatchedKey
+ raw["_sign_expected"] = jsonString(verify.Expected)
+ raw["_sign_base_strings"] = jsonString(verify.BaseString)
+ return raw
+}
+
+func jsonString(value map[string]string) string {
+ if len(value) == 0 {
+ return "{}"
+ }
+ raw, err := json.Marshal(value)
+ if err != nil {
+ return "{}"
+ }
+ return string(raw)
+}
+
func newPaymentNo() (string, error) {
buf := make([]byte, 4)
if _, err := rand.Read(buf); err != nil {
@@ -547,21 +590,3 @@ func firstNonEmpty(values ...string) string {
}
return ""
}
-
-func shortExpectedSigns(values map[string]string) map[string]string {
- out := map[string]string{}
- for key, value := range values {
- out[key] = shortSign(value)
- }
- return out
-}
-
-func shortSign(value string) string {
- if value == "" {
- return ""
- }
- if len(value) <= 12 {
- return value
- }
- return value[:12] + "..."
-}
diff --git a/backend/internal/modules/payment/service.go b/backend/internal/modules/payment/service.go
index 472fe53..5cf3921 100644
--- a/backend/internal/modules/payment/service.go
+++ b/backend/internal/modules/payment/service.go
@@ -10,6 +10,8 @@ var (
ErrPaymentNotFound = errors.New("payment not found")
)
+const MinWalletRechargeAmount = 0.01
+
type Service struct {
repo *Repository
}
@@ -42,7 +44,7 @@ func (s *Service) StartWalletRecharge(userID uint64, req WalletRechargePaymentRe
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
- if userID == 0 || req.Amount <= 0 {
+ if userID == 0 || req.Amount < MinWalletRechargeAmount {
return nil, ErrPaymentCannotStart
}
return s.repo.StartWalletRecharge(userID, req, clientIP)
@@ -58,9 +60,9 @@ func (s *Service) QueryWalletRecharge(userID uint64, paymentID uint64) (*Payment
return s.repo.QueryWalletRecharge(userID, paymentID)
}
-func (s *Service) HandleLeshuaNotify(params map[string]string) (*NotifyResult, error) {
+func (s *Service) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
- return s.repo.HandleLeshuaNotify(params)
+ return s.repo.HandleLeshuaNotify(params, rawPayload, contentType)
}
diff --git a/backend/internal/modules/wallet/service.go b/backend/internal/modules/wallet/service.go
index d7b46c5..0774cbb 100644
--- a/backend/internal/modules/wallet/service.go
+++ b/backend/internal/modules/wallet/service.go
@@ -8,6 +8,8 @@ var (
ErrInsufficientBalance = errors.New("insufficient balance")
)
+const MinRechargeAmount = 0.01
+
type Service struct {
repo *Repository
}
@@ -34,7 +36,7 @@ func (s *Service) Recharge(userID uint64, req RechargeRequest) (*AccountDTO, err
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
- if req.Amount <= 0 {
+ if req.Amount < MinRechargeAmount {
return nil, ErrInvalidAmount
}
return s.repo.Recharge(userID, req.Amount)
diff --git a/docs/乐刷商户交易.md b/docs/乐刷商户交易.md
new file mode 100644
index 0000000..abe7e25
--- /dev/null
+++ b/docs/乐刷商户交易.md
@@ -0,0 +1,1699 @@
+##
+### API目录
+| **分类** | **接口中文名** | **接口英文名** | **描述** |
+| --- | --- | --- | --- |
+| 下单接口 | [统一下单接口](#YGAT6) | /cgi-bin/lepos_pay_gateway
.cgi | 主扫,C扫B。消费者主动扫码。 |
+| 条码支付 | [条码支付](#AGDJI) | /cgi-bin/lepos_pay_gateway.cgi | 被扫,B扫C。消费者出示付款码被扫。 |
+| 交易结果 | [支付结果通知](#93D6z) | / | 返回支付结果。**影响推送的因素较多,建议接交易结果查询接口。** |
+| | [交易结果查询](#yEuUU) | /cgi-bin/lepos_pay_gateway.cg | 查询交易结果 |
+| 退款 | [退款](#Mh3kb) | /cgi-bin/lepos_pay_gateway.cgi | 进行退款操作 |
+| | [退款查询](#2D2fx) | /cgi-bin/lepos_pay_gateway.cgi | 查询退款信息 |
+| | [退款结果通知](#ZQ0tK) | | 查看退款结果 |
+| 订单关闭接口 | [订单关闭](#z9MWc) | /cgi-bin/lepos_pay_gateway.cgi | 关闭订单 |
+| 授权码 | [授权码查询用户openid](#F3rn1) | /cgi-bin/lepos_pay_gateway.cgi | 查询openid |
+| | [授权码获取银联云闪付用户ID](#DprGi) | | 获取云闪付用户ID |
+| 异步通知 | [刷卡、扫码支付异步通知](#ZD2Om) | | |
+
+
+### ****数字签名
+(1)为了保证数据传输过程中的数据真实性和完整性,我们需要对数据进行数字签名,在接收签名数据之后进行签名校验。
+
+(2)签名有两个步骤,先按一定规则拼接要签名的原始串,再选择具体的算法和密钥计算出签名结果。
+
+(3)原始串中,字段名和字段值都采用原始值,不进行URL Encode。
+
+(4)平台返回的应答或通知消息可能会由于升级增加参数,请验证应答签名时注意允许这种情况。
+
+
+
+### 签名方法
+(1)设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
+
+(2)在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
+
+
+
+### 签名样例
+(1)假设需要传递的参数如下:
+
+```plain
+server:query_status
+merchant_id:1234567890
+third_order_id:12345678901
+nonce_str:12345678901
+```
+
+
+
+(2)对参数按照key=value的格式,并按照参数名ASCII字典序排序如下
+
+```plain
+stringA=merchant_id=1234567890&nonce_str=12345678901&server=query_status&third_order_id=12345678901
+```
+
+
+
+(3)拼接商户秘钥key
+
+```plain
+stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户密钥key
+```
+
+
+
+(4)计算签名
+
+```plain
+交易报文MD5计算:sign=MD5(stringSignTemp).toUpperCase()
+通知报文MD5计算:sign=MD5(stringSignTemp).toLowerCase()
+交易报文SM3计算:sign=SM3(stringSignTemp).toUpperCase()
+通知报文SM3计算:sign=SM3(stringSignTemp).toLowerCase()
+```
+
+注:md5加密为32位。
+**注**:SM3签名为64位
+(1)设所有请求数据为集合M(请求数据中需上送**sign_type**为**SM3**,不上送默认为使用MD5),将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),
+
+使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
+
+(2)在stringA最后拼接上key得到stringSignTemp字符串,
+
+并对stringSignTemp进行SM3运算,再将得到的字符串所有字符转换为大写,得到sign值signValue
+
+### 特别注意
+(1)请求数据验签方法
+
+```plain
+除sign、leshua、resp_code字段外,其他参数按照签名方法验签,空值不传递,不参与签名组串。
+```
+
+
+
+(2)应答数据验签方法
+
+```plain
+除sign、leshua、resp_code字段外,其他参数按照签名方法验签,空值参与签名组串。
+(注:微信刷脸接口是全字段加签)
+```
+
+
+
+(3)支付结果通知验签方法
+
+```plain
+除sign、leshua、error_code字段外,其他参数按照签名方法验签,空值参与签名组串。
+```
+
+商户维度接入,支付结果通知验签需要向商务申请 商户获取代理商解析密钥
+
+### 判断付款码规则
+
+```java
+支付宝:支付授权码,25~30开头的长度为16~24位的数字, 实际字符串长度以开发者获取的付款码长度为准
+微信:扫码支付授权码,设备读取用户微信中的条码或二维码信息(注:用户刷卡条形码规则:18位纯数字以10、11、12、13、14、15开头)
+银联二维码:62开头19位数字
+数字人民币:0100开头的数字,其中01002 工行(数字人民币的不完整,后续会有改动)
+01003 农行
+01004 中行
+01005 建行
+01007 网商
+01008 邮储
+01009 交通银行
+```
+
+### 1、统一下单(主扫:C扫B)
+#### 1.1接口说明
+代理商在C扫B场景调用此支付接口完成下单,支持支付宝拉码支付、公众号支付、服务窗支付、银联JS支付、微信小程序支付。
+
+测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司。
+
+
+
+#### 1.2请求方式
+POST
+
+
+
+#### 1.3请求地址
+测试环境域名:https://t-paygate.lepass.cn
+
+生产环境域名:https://paygate.leshuazf.com
+
+接口地址:/cgi-bin/lepos_pay_gateway.cgi
+
+
+
+#### 1.4频率限制
+4000次/s
+
+
+
+#### 1.5业务入参
+
+
+| **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- |
+| service | M | 无 | string | **接口名**
get_tdcode(此为固定值) |
+| t0 | O | 无 | int | **T0交易标志**
默认为0,0:d1交易 1:d0交易 |
+| sign_type | 0 | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| pay_way | M | 16 | string | **支付类型**
详见下方[支付类型](#nlHUH) |
+| merchant_id | M | 10 | string | **乐刷商户号**
由乐刷分配 |
+| user_name | O | 无 | string | 收银员名称 |
+| third_order_id | M | 64 | string | **商户内部订单号**
可以包含字母:确保同一个商户下唯一 |
+| amount | M | 10 | string | **订单总金额**
金额不能为零或负数 |
+| jspay_flag | M | 1 | **string** | **支付类型**
0-支付宝Native扫码支付、银联Native扫码支付;
1-微信JSAPI、支付宝JSAPI支付、银联JSAPI支付;
2-微信、支付宝简易支付<跳转乐刷收银台支付>;
(jspay_flag=2时必传jump_url,否则会报错)
3-微信小程序支付、支付宝小程序支付
注:
1)微信拉码支付已下线;
2)如需接入银联JS支付,请联系乐刷运营沟通域名报备。
3)数字货币支付当前仅支持jspay_flag=0 |
+| royalty | O | 1 | string | 交易分账标识
0:普通交易 1:分账(用于分账的交易需传该参数) 2:交易主体分账(延迟结算)
3:预授权
注:如果未传该字段默认为0,按不分账处理 |
+| appid | M | 32 | string | **appid**
条件必填,微信支付时必填。填微信公众号支付的公众号id或微信小程序支付的小程序appid;
传了会使用此appid 进行下单 |
+| sub_openid | [C](#eFgvt) | 32 | string | **sub_openid**
微信JSAPI、微信小程序、支付宝JSAPI、支付宝小程序、银联JSAPI支付必填 |
+| extend_business_params | O | 无 | string | 该字段 为JSON格式的字符串,当前可透传支付宝的参数见下表
具体格式详见文档下方:[业务拓展参数示例](#5u5k5)注:花呗分期商家订单传参贴息示例:
"extend_business_params":"{\"business_params\":{ \"enable_thirdparty_subsidy\":\"N\"}}"
如果第三⽅贴息活动为全场贴息,默认可贴息,传⼊ N 值则本笔交易禁⽤三⽅贴息;
如果第三⽅贴息活动为指定订单传参贴息,默认禁⽤贴息,传⼊Y 值则本笔交易启⽤三⽅贴息 |
+| jump_url | O | 128 | string | **前台跳转地址**
简易支付时必填,完成后,乐刷将跳转到该页面,需做UrlEncode 处理
(受微信支付宝限制,已失效,可不传) |
+| notify_url | O | 128 | string | **通知地址**
接收乐刷通知(支付结果通知)的URL,需做UrlEncode 处理,需要绝对路径,确保乐刷能正确访问,若不需要回调请忽略 |
+| client_ip | O | 16 | string | **商户发起交易的IP地址** |
+| body | O | 256 | string | **商品描述**
不能包含回车换行等特殊字符 |
+| shop_no | O | 16 | string | **商户门店编号**
只能是汉字、英文字母、数字。注:该参数不上传给微信、支付宝 |
+| pos_no | O | 16 | string | **商户终端编号**
只能是汉字、英文字母、数字 注意:银联类型交易时,只能 8位:数字字母 不支持 特殊字符 |
+| attach | O | 96 | string | **附加数据**
下单成功原样返回;注意:只能是汉字、英文字母、数字 |
+| limit_pay | O | 1 | string | **指定支付方式**
1:禁止使用信用卡;
0或者不填:不限制 |
+| goods_tag | O | 32 | string | **订单优惠标记**
订单优惠标记(订单级别-品类级别),透传给微信,对应微信的`goods_tag`字段。微信会自动进行优惠匹配计算和核销。
用于给整个订单打上一个"标签",主要用于**代金券立减优惠场景**,示例:`"coffee"`。 |
+| goods_detail | O | 8000 | string | **单品详情**
**微信**
单品级详细信息,透传给微信,对应微信的`detail`字段,**注意**不是对应`detail.goods_detail`字段。微信会自动进行优惠匹配计算和核销。
按微信单品优惠券格式传递透传给微信,请做UrlEncode
示例:`{"goods_detail":[{"merchant_goods_id":"xiaomi_14_pro","goods_name":"小米14 Pro","quantity":1,"unit_price":499900}]}`
**银联**
银联扫码交易时,透传给银联的“收款方附加数据”acqAddnData参数,当前银联的单品营销及扫码点餐均使用到该参数,具体参数格式及说明见:[银联收款方附加数据](https://www.yuque.com/hayley-boppa/ws2xbg/tu6kh5hh2kegkz0c#lUVoy)。 |
+| order_expiration | O | 无 | string | **订单有效时间**
单位:秒(支付宝的超时时间最小粒度为分钟,建议上送的为60的整数倍)最大时效600s |
+| hb_fq_num | O | 无 | string | **花呗分期数**
支付宝花呗分期数,支持3、6、12期 |
+| front_url | C | 无 | string | **前端跳转地址**
银联JSAPI支付时选填,支付成功时跳转 |
+| front_fail_url | C | 无 | string | **支付失败前端跳转地址**
银联JSAPI支付时选填,支付失败时跳转 |
+| nonce_str | M | 32 | string | **随机字符串** |
+| sign | M | 32 | string | **签名**
MD5签名结果 |
+| device_info | O | 32 | string | **设备编号**
针对微信、支付宝有效,透传至银联。
微信:数字、字母、下划线格式
支付宝:目前支持非0开头的数字 |
+| store_id | O | 32 | string | **门店编号**
针对微信、支付宝有效,透传至银联。
微信:数字、字母、下划线格式 |
+| ass_merchant_id | O | 32 | string | **通道商户号**
非必填。可使用指定的微信、支付宝子商户号进行交易,一个乐刷商户号有多个通道商户号情况下可用。
注:对应乐刷商户号大于200条时不能传该参数 |
+| pnrins_id_cd | O | 32 | string | **银联服务商标识**
银联扫码交易时,透传给银联,对应银联的 pnrInsIdCd参数。 |
+| gps_info | O | 512 | string | **gps信息**
校验GPS信息格式, 如:-128.12,23.1 -- 1. xxx,xxx -- 2. 经度xxx为[-180,180]之间的浮点数,维度xxx为[-90,90]之间的浮点数,最多保留小数点八位float(11,8) |
+| bs_info | O | 512 | string | **基站信息**
校验基站信息格式,
格式说明: -- 1. 格式为:xxx,xxx,xxx,xxx 如:460,1,12,23454 -- 2. xxx均为整数,长度不超过11位
基站信息,从左至右依次对应以下几个字段: mcc: 移动国家号码,由3位数字组成,唯一地识别移动用户所属的国家。我国为460 mnc:移动网号,由两位数字组成,用于识别移动用户所归属的移动网 lac:位置区编码,为寻呼而设置的一个区域,覆盖一片地理区域,按寻呼量划分 ci :负责收发的天线所朝向的扇区编号 |
+| extend_business_params | O | - | string | 见下extend_business_params参数表 |
+| scene_info | O | - | string | 该字段用于上报场景信息,仅针对微信交易有效,目前支持上报实际门店信息。该字段 为JSON格式的字符串,对象格式为{"store_info":{"id": "门店 ID","name ": "名称","area_code": "编码","address": "地址"}} ,字段详细说明参考下文。 |
+| need_receipt | O | - | boolean | 电子发票功能。仅针对微信交易有效,需要和微信公众平台的发票功能联合使用。
枚举:
(只能为true或false,只支持全小写字母或全大写字母)
1. true
2. false |
+| terminal_info | M | - | **String** | 商户侧受理终端信息
**terminal_info为String类型,内容为json**:
terminal_info="{\"longitude\":\"-121.48352\",\"latitude\":\"+31.221345\",\"network_license\":\"P3100\",\"device_type\":\"01\",\"device_id\":\"54MPDz39\",\"serial_num\":\"5\",\"app_version\":\"v1.1.1\",\"device_ip\":\"252.1.1.25\"}"
**terminal_info不能为空**,如无终端信息则按此规则传参:**device_type和serial_num必传:**
**device_type固定传11**
**serial_num=lhsd+商户编号**
json内各参数说明
longitude:经度,+代表东经,-代表西经。
latitude:纬度,+代表北纬,-代表南纬。
network_license:银行卡受理终端入网编号。该
编号由“中国银联标识产品企业资质认证办公室”为通过入网认证的终端进行 分配。银联直连终端必填。
格式:5 位字符,例如 P3100
device_type:设备类型,01:自动柜员机(含 ATM 和 CDM)和 多媒体自助终端
02:传统 POS
03:mPOS
04:智能 POS
05:II 型固定电话
06:云闪付终端;
07:保留使用;
08:手机 POS;
09:刷脸付终端;
10:条码支付受理终端;
11:条码支付辅助受理终端;
12:行业终端(公交、地铁用于指定行
业的终端);
13:MIS 终端;
serial_num:设备序列号,设备类型02、
03、04、05、06、08、09 或 10 时必填
encrypt_rand_num:仅在被扫支付类交易报文中出现:若付 款码为 19 位数字,则取后 6 位; 若付款码码为 EMV 二维码,则取其 tag 57 的卡号/token 号的后 6 位
secret_text:仅在条码支付交易报文中出现:64bit
的密文数据,对终端硬件序列号和加密 随机因子加密后的结果。 本子域取值为:64bit 密文数据进行 base64 编码后的结果。该字段需要服务商和厂商联调时由厂商sdk之类加密后给出。
app_version:终端应用程序的版本号。应用程序变更
应保证版本号不重复。当长度不足时, 右补空格。固定8位
device_ip:终端交易IP。如经、维度信息未上送,该字段必送。 |
+
+
+**extend_business_params 参数表**
+
+| **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | :---: | :---: | :---: | --- |
+| business_params | O | - | String | |
+| goods_detail | O | - | String | |
+| extend_params | O | - | String | |
+| seller_id | O | 28 | String | 卖家支付宝用户 ID。如果该值为空,则默认为商户签约账号对应的支付宝用户 ID |
+| discountable_amont | O | 11 | Price | 参与优惠计算的金额,单位为元,精确到 小 数 点 后 两 位 , 取值范围[0.01,100000000]。 如果该值未传入,但传入了【订单总金额】和【不可打折金额】,则该值默认为【订单总金额】-【不可打折金额】 |
+| undiscountable_amount | O | 11 | Price | 不参与优惠计算的金额,单位为元,精确 到 小 数 点 后 两 位 , 取 值 范 围[0.01,100000000]。如果该值未传入,但传入了【订单总金额】和【可打折金额】,则该值默认为【订单总金额】-【可打折金额】 |
+| buyer_logon_id | O | 100 | String | 买家支付宝账号 |
+| operator_id | O | 28 | String | 商户操作员编号 |
+| enable_pay_channels | O | 128 | String | 可用渠道,用户只能在指定渠道范围内支付。当有多个渠道时用“,”分隔,与 disable_pay_channels 互 斥。 |
+| settle_info | O | - | SettleInfo | 描述结算信息,json 格式,详见结算参数说明 |
+| alipay_store_id | O | 32 | String | 支付宝的店铺编号 |
+| ext_user_info | O | - | ExtUserInfo | 外部指定买家 |
+| qr_code_timeout_express | O | 6 | String | 该笔订单允许的最晚付款时间,逾期将关闭交易,从生成二维码开始计时。取值范围:1m~15d。 m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在 0 点关闭)。 该参数数值不接受小数点,如 1.5h,可转换为90m。
(对应jspay_flag为0时) |
+| merchant_order_no | O | 32 | String | 商户原始订单号,最大长度限制32 位
(对应jspay_flag为1/2/3时) |
+| disable_pay_channels | O | 64 | String | 禁用支付渠道,多个渠道以逗号分割,如 同时禁用信用支付类型和积分,则 disable_pay_channels="cre dit_group,point" 具体的渠道以支付宝或者银联提供的为准 |
+
+
+**场景信息scene_info字段说明(当前仅针对微信交易会透传给微信):**
+
+| **名称** | **参数名** | **必填** | **类型** | **示例值** | **描述** |
+| --- | --- | --- | --- | --- | --- |
+| 门店Id | id | 否 | String(32) | SZTX001 | 门店唯一标识 |
+| 门店名称 | name | 否 | String(64) | 腾讯大厦腾大餐厅 | 门店名称 |
+| 门店行政区划码 | area_code | 否 | String(6) | 440305 | 门店所在地行政区划码 |
+| 门店详细地址 | address | 否 | String(128) | 科技园中一路腾讯大厦 | 门店详细地址 |
+
+
+#### 1.6业务出参
+| **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- |
+| resp_code | M | 无 | string | **返回状态码**
0 - 成功,非0 - 失败。注:此字段是通信标识,是否获取到二维码要看result_code |
+| resp_msg | C | 无 | string | **返回错误信息**
错误描述:resp_code非0时返回 |
+| result_code | M | 1 | string | **业务结果**
0 - 成功,非0 - 失败 |
+| error_code | O | 无 | string | **错误码**
[参考错误码信息表](#rOC0m) |
+| error_msg | O | 无 | string | **错误信息描述** |
+| attach | O | 96 | string | **附加数据**
原样返回;注意:只能是汉字、英文字母、数字 |
+| merchant_id | M | 10 | string | **乐刷商户号**
由乐刷分配 |
+| sub_merchant_id | M | 无 | string | **通道商户号**
微信、支付宝、QRC商户号 |
+| third_order_id | M | 64 | string | **商户内部订单号** |
+| nonce_str | M | 32 | string | **随机字符串** |
+| sign | M | 32 | string | **MD5签名结果** |
+| td_code | C | 无 | string | **二维码链接**
非公众号支付返回,可直接通过该链接生成二维码扫码支付(jspay_flag传0-2该字段才会返回) |
+| jspay_info | C | 无 | string | **支付信息**
原生公众号、服务窗、小程序,返回json格式字符串、银联JS支付返回URL,用云闪付打开此链接即可调起支付 生效时间:默认10分钟,具体时间看订单有效时间 |
+| jspay_url | C | 无 | string | **支付跳转地址**
简易支付时返回。重定向到该url可以完成后续支付流程。返回二维码链接有效期为10分钟; |
+| leshua_order_id | M | 32 | string | **乐刷订单号** |
+| pay_way | M | 无 | string | **支付类型**
[详见下方支付类型](#nlHUH) |
+| cost_time | C | 无 | string | **请求耗时**
请求接口耗费的时间 |
+| channel_flag | O | 32 | string | **通道标记**
GXST:高校食堂
PUBWEL:公益
PUBPAY:公缴
ZFBLH:支付宝新蓝海
SLZXY:私立中小幼
INS:保险
ONLINE:线上
YLLZ:绿洲 |
+| alipay_infos | O | | | trade_no:银联交易号 |
+
+
+**注意事项**
+
+(1)所有涉及到金额的单位都位分,币种为RMB,最小为1分,不允许出现小数
+
+(2)文档中参数,标识为必填必须上送(如果缺少会报错),非必填的可填可不填(简易支付"支付跳转地址"字段为必传),
+
+(3)返回参数中必填为是的参数是一定会返回的,必填为否的参数则不一定返回,因升级或配置等情况实际返回参数可能不会跟文档完全一致,必须以实际接收到的参数为准
+
+
+
+##### 获取微信用户openid
+```http
+https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN
+```
+
+##### 获取支付宝用户openid
+```http
+https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.8ujLD6&treeId=115&articleId=104114&docType=1
+```
+
+
+
+
+
+**公众号支付请求示例**
+
+1、请求格式如下:
+
+```json
+https://paygate.leshuazf.com/cgi-bin/lepos_pay_gateway.cgi?amount=1&
+appid=wx00e59fa8be9ba128&jspay_flag=1&merchant_id=3219113278&
+nonce_str=lnxouwc0r7l93453x5&order_expiration=60&pay_way=WXZF&service=get_tdcode&
+sub_openid=oe5BX0qaVuC5vqYdj65GlUcyAVUM&third_order_id=202004271809453917&sign=2A500B7F906284717212304A9BCFB33D
+```
+
+
+
+**返回示例**
+
+1、响应格式如下:
+
+```json
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+**支付宝拉码支付请求示例**
+
+1、请求格式如下:
+
+```json
+https://t-paygate.lepass.cn/cgi-bin/lepos_pay_gateway.cgi?amount=1&jspay_flag=0
+&merchant_id=0000000018&nonce_str=w1hxpdiu9nkjfw5qrp&order_expiration=60&
+pay_way=ZFBZF&service=get_tdcode&third_order_id=202004291733230374&
+sign=340DB607E3BEE2BAE60807B3601008E2
+```
+
+
+
+**返回示例**
+
+1、响应格式如下:
+
+```json
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+### 2、条码支付(被扫:B扫C)
+
+
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | [M](#eFgvt) | 无 | string | upload_authcode(此为固定值) |
+| t0交易标志 | t0 | O | 无 | int | 默认为0,0:d1交易 1:d0交易 |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 付款码 | auth_code | M | 无 | string | 支持以下付款码:
1. 微信数字付款码
2. 支付宝数字付款码
3. 云闪付APP 62开头付款码
4. 银行APP 62开头付款码
5. 数字人民币APP付款码(0100开头)
6. 支付宝刷脸付款码(fp开头) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号,可以包含字母:确保同一个商户下唯一 |
+| 订单金额 | amount | M | 10 | string | 总金额 |
+| 分账标识 | royalty | O | 1 | string | 交易分账标识
0:普通交易 1:分账(用于分账的交易需传该参数) 2:交易主体分账(延迟结算)
3:预授权
注:如果未传该字段默认为0,按不分账处理 |
+| 商户公
众账号 ID | appid | O | 32 | string | 商户或者商户所属渠道号主体的公众号appid,由微信统一分配,仅对微信交易生效,传送前请确定商户和该appid已经建立绑定关系 |
+| 通知地址 | notify_url | [O](#eFgvt) | 128 | string | 接收乐刷通知的URL,需做UrlEncode 处理,需要绝对路径,确保乐刷能正确访问,若不需要回调请忽略 |
+| 用户IP地址 | client_ip | O | 16 | string | 商户发起交易的IP地址 |
+| 商品描述 | body | O | 256 | string | 商品描述,不能包含回车换行等特殊字符 |
+| 商户门店编号 | shop_no | O | 16 | string | 只能是汉字、英文字母、数字 |
+| 商户终端编号 | pos_no | O | 16 | string | 只能是汉字、英文字母、数字 注意:银联类型交易时,只能 8位:数字字母 不支持 特殊字符 |
+| 附加数据 | attach | O | 96 | string | 支付成功原样返回;注意:只能是汉字、英文字母、数字 |
+| 指定支付方式 | limit_pay | O | 1 | string | 1:禁止使用信用卡;0或者不填:不限制 |
+| 订单优惠标记 | goods_tag | O | 32 | string | 订单优惠标记,透传给微信 |
+| 商品详情 | goods_detail | O | 8000 | string | 按[微信单品优惠券格式](https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1)传递,透传给微信;
银联扫码交易时,透传给银联的“收款方附加数据”acqAddnData参数,当前银联的单品营销及扫码点餐均使用到该参数,具体参数格式及说明见:[银联收款方附加数据](#lUVoy)。 |
+| 花呗分期数 | hb_fq_num | O | 无 | string | 支付宝花呗分期数,支持3、6、12期 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 业务拓展参数 | extend_business_params | O | 8000 | string | 该字段 为JSON格式的字符串,当前可透传支付宝的参数见下表
具体格式详见文档下方:[业务拓展参数示例](#5u5k5)
注:花呗分期商家订单传参贴息示例:
"extend_business_params":"{\"business_params\":{ \"enable_thirdparty_subsidy\":\"N\"}}"
如果第三⽅贴息活动为全场贴息,默认可贴息,传⼊ N 值则本笔交易禁⽤三⽅贴息;
如果第三⽅贴息活动为指定订单传参贴息,默认禁⽤贴息,传⼊Y 值则本笔交易启⽤三⽅贴息 |
+| 设备编号 | device_info | O | 32 | string | 针对微信、支付宝有效,透传至银联。
微信:数字、字母、下划线格式
支付宝:目前支持非0开头的数字 |
+| 门店编号 | store_id | O | 32 | string | 针对微信、支付宝有效,透传至银联。
微信:数字、字母、下划线格式
支付宝:目前支持非0开头的数字 |
+| 通道商户号 | ass_merchant_id | O | 32 | string | 非必填。可使用指定的微信、支付宝子商户号进行交易,一个乐刷商户号有多个通道商户号情况下可用。
注:对应乐刷商户号大于200条时不能传该参数 |
+| 银联服务商标识 | pnrins_id_cd | O | 32 | string | 银联扫码交易时,透传给银联,对应银联的 pnrInsIdCd参数。 |
+| **gps信息** | gps_info | O | 512 | string | 校验GPS信息格式, 如:-128.12,23.1 -- 1. xxx,xxx -- 2. 经度xxx为[-180,180]之间的浮点数,维度xxx为[-90,90]之间的浮点数,最多保留小数点八位float(11,8) |
+| ** 基站信息** | bs_info | O | 512 | string | 校验基站信息格式,
格式说明: -- 1. 格式为:xxx,xxx,xxx,xxx 如:460,1,12,23454 -- 2. xxx均为整数,长度不超过11位
基站信息,从左至右依次对应以下几个字段: mcc: 移动国家号码,由3位数字组成,唯一地识别移动用户所属的国家。我国为460 mnc:移动网号,由两位数字组成,用于识别移动用户所归属的移动网 lac:位置区编码,为寻呼而设置的一个区域,覆盖一片地理区域,按寻呼量划分 ci :负责收发的天线所朝向的扇区编号 |
+| 场景信息 | scene_info | O | | string | 该字段用于上报场景信息,仅针对微信交易有效,目前支持上报实际门店信息。该字段 为JSON格式的字符串,对象格式为{"store_info":{"id": "门店 ID","name ": "名称","area_code": "编码","address": "地址"}} ,字段详细说明参考下文。 |
+| 电子发票功能 | need_receipt | O | | boolean | 电子发票功能。仅针对微信交易有效,需要和微信公众平台的发票功能联合使用。
枚举:
(只能为true或false,只支持全小写字母或全大写字母)
1. true
2. false |
+| 交易终端信息 | terminal_info | O | | String | 商户侧受理终端信息,格式为json 格 式。 如terminal_info= { "longitude":"-121.48352",#option "latitude":"+31.221345",#option
"network_license":"P3100", "device_type":"01", "device_id":"54MPDz39", "serial_num":"5", "app_version": "v1.1.1" , "device_ip": "252.1.1.25" , }
json内各参数说明
longitude:经度,+代表东经,-代表西经。
latitude:纬度,+代表北纬,-代表南纬。
network_license:银行卡受理终端入网编号。该
编号由“中国银联标识产品企业资质认证办公室”为通过入网认证的终端进行 分配。银联直连终端必填。
格式:5 位字符,例如 P3100
device_type:设备类型,01:自动柜员机(含 ATM 和 CDM)和 多媒体自助终端
02:传统 POS
03:mPOS
04:智能 POS
05:II 型固定电话
06:云闪付终端;
07:保留使用;
08:手机 POS;
09:刷脸付终端;
10:条码支付受理终端;
11:条码支付辅助受理终端;
12:行业终端(公交、地铁用于指定行
业的终端);
13:MIS 终端;
serial_num:设备序列号,设备类型02、
03、04、05、06、08、09 或 10 时必填
encrypt_rand_num:仅在被扫支付类交易报文中出现:若付 款码为 19 位数字,则取后 6 位; 若付款码码为 EMV 二维码,则取其 tag 57 的卡号/token 号的后 6 位
secret_text:仅在条码支付交易报文中出现:64bit
的密文数据,对终端硬件序列号和加密 随机因子加密后的结果。 本子域取值为:64bit 密文数据进行 base64 编码后的结果。该字段需要服务商和厂商联调时由厂商sdk之类加密后给出。
app_version:终端应用程序的版本号。应用程序变更
应保证版本号不重复。当长度不足时, 右补空格。固定8位
device_ip:终端交易IP。如经、维度信息未上送,该字段必送。
|
+
+
+extend_business_params参数:
+
+| **变量名** | **必填** | **限制** | **类型** | **说明** | 示例 |
+| --- | --- | --- | --- | --- | --- |
+| business_params | O | - | Object | 商户传入业务信息,应用于安全,营销
等参数直传场景,格式为 json 格式。 | |
+| goods_detail | O | - | Array | 订单包含的商品列表信息,数组格式。
一般在支付宝扫码点餐业务中上传点餐的商品信息 | [{"goods_id": "5544", "goods_name": "爽口青笋丝","price": "0.50","quantity": 2,"goods_category": "888", "categories_tree": "888","body": "爽口青笋丝","show_url":"pageFoodChain/storeDetail/main?suid=10"}] |
+| ┖goods_id | M | 32 | String | 商品的编号 | |
+| ┖alipay_goods_id | O | 32 | String | 支付宝定义的统一商品编号 | |
+| ┖goods_name | M | 256 | String | 商品名称 | |
+| ┖quantity | M | 10 | Number | 商品数量 | |
+| ┖price | M | 9 | Price | 商品价格,单位为元 | |
+| ┖goods_category | O | 24 | String | 商品类目 | |
+| ┖categories_tree | O | 128 | String | 商品类目数,从商户品类目根节点到叶子节点的类目id组成,类目id使用|分割 | 124868003|126
232002|126252
004 |
+| ┖body | O | 1000 | String | 商品描述信息 | |
+| ┖show_url | O | 400 | String | 商品的展示地址 | http://www.alipay.co
m/xxx.jpg |
+| extend_params | O | - | Object | 支付宝业务扩展参数 | |
+| ┖sys_service_provid
er_id | O | | String | | |
+| ┖hb_fq_num | O | | String | | |
+| ┖hb_fq_seller_percent | O | | String | | |
+| ┖industry_reflux_info | O | | String | | |
+| ┖card_type | O | | String | | |
+| | | | | | |
+| | | | | | |
+| ┖ | | | | | |
+| ┖ | | | | | |
+| ┖ | | | | | |
+| ┖ | | | | | |
+| seller_id | O | 28 | String | 如果该值为空,则默认为商户签约账号对应的支付宝用户ID预授权场景下无需上送 | |
+| discountable_amont | O | 11 | Price | 参与优惠计算的金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]。 如果该值未传入,但传入了【订单总金额】和【不可打折金额】,则该值默认为【订单总金额】-【不可打折金额】 | |
+| undiscountable_amount | O | 11 | Price | 不参与优惠计算的金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]。如果该值未传入,但传入了【订单总金额】和【可打折金额】,则该值默认为【订单总金额】-【可打折金额】 | |
+| operator_id | O | 28 | String | 商户操作员编号 | |
+| alipay_store_id | O | 32 | String | 支付宝的店铺编号 | |
+| merchant_order_no | O | 32 | String | 商户的原始订单号 | |
+| ext_user_info | O | - | ExtUserInfo | 外部指定买家 | |
+| promo_params | O | 512 | PromoParam | 优惠明细参数,通过此属性补充营销参数 | |
+| terminal_params | O | 2048 | String | json 格式;商户传入终端设备。如:
{"credential":"28763443825664394:20180207192030954:abcdefGHIJKLMN","signature":"xxxxxxx","terminalType":"IOT"} | |
+| advance_payment_type | O | 20 | String | 支付模式类型, 若 值 为ENJOY_PAY_V2表示当前交易允许走先享后付 2.0 垫资 | |
+| query_options | O | 1024 | String[] | 返回查询选项,商户通过上送该参数来定制同步需要额外返回的信息字段,数组格式。如:["fund_bill_list","voucher_detail_list","discount_goods_detail"] | |
+| disable_pay_channels | O | 64 | String | 禁用支付渠道,多个渠道以逗号分割,如 同时禁用信用支付类型和积分,则 disable_pay_channels="cre dit_group,point" 具体的渠道以支付宝或者银联提供的为准 | |
+
+
+**场景信息scene_info字段说明(当前仅针对微信交易会透传给微信):**
+
+| **名称** | **参数名** | **必填** | **类型** | **示例值** | **描述** |
+| --- | --- | --- | --- | --- | --- |
+| 门店Id | id | 否 | String(32) | SZTX001 | 门店唯一标识 |
+| 门店名称 | name | 否 | String(64) | 腾讯大厦腾大餐厅 | 门店名称 |
+| 门店行政区划码 | area_code | 否 | String(6) | 440305 | 门店所在地行政区划码 |
+| 门店详细地址 | address | 否 | String(128) | 科技园中一路腾讯大厦 | 门店详细地址 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | [C](#eFgvt) | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 支付类型 | pay_way | M | 无 | string | [详见下方支付类型](#nlHUH) |
+| 支付完成时间 | pay_time | C | 无 | string | 支付成功时才返回 |
+| 银行类型 | bank_type | O | 无 | string | 使用银行卡支付以外的(如零钱)全部展示为others,使用银行卡支付的详见下方[付款银行类型](#cX4pl) |
+| 用户openid | openid | C | 无 | string | 支付成功时才返回 |
+| 微信、支付宝等订单号 | out_transaction_id | C | 无 | string | 支付成功时才返回 |
+| 用户子标识 | sub_openid | C | 无 | string | 支付成功时才返回。微信:公众号APPID下用户唯一标识;支付宝:买家的支付宝用户ID |
+| 附加数据 | attach | O | 96 | string | 支付成功原样返回;注意:只能是汉字、英文字母、数字 |
+| 交易类型 | trade_type | C | 无 | string | 支付成功时才返回:MICROPAY-条码支付,NATIVE-原生扫码支付,JSAPI-公众号支付、服务窗支付,SmPgPay-小程序支付,JSAPIQuick-简易支付 |
+| 通道订单号 | channel_order_id | C | 无 | string | 支付成功时才返回 |
+| 通道订单时间 | channel_datetime | C | 无 | string | 支付成功时才返回 |
+| 支付宝红包金额 | coupon | C | 无 | string | 支付成功时才返回,单位(分) |
+| 应结算金额 | settlement_amount | C | 无 | string | 实际结算金额,支付成功时才返回,单位(分) |
+| 折扣优惠金额 | discount_amount | C | 无 | string | [订单优惠金额](#6QKR6),支付成功时才返回,单位(分) |
+| 优惠详情 | promotion_detail | O | 无 | string | 银联单品的具体优惠详情;
微信优惠详情说明:[微信官网](https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1) |
+| 活动标志 | active_flag | O | 无 | string | 活动标志。WXLZ:微信绿洲;ZFBLH:支付宝蓝海 |
+| 买家实付金额 | buyer_pay_amount | C | 无 | String | 微信、支付宝此值有效 |
+| 请求耗时 | cost_time | C | 无 | string | 请求接口耗费的时间 |
+| 通道标记 | channel_flag | O | 32 | string | GXST:高校食堂
PUBWEL:公益
PUBPAY:公缴
ZFBLH:支付宝新蓝海
SLZXY:私立中小幼
INS:保险
ONLINE:线上 |
+| 银联/网联状态码 | channel_code | C | 无 | JSON | 透传银联的返回码。
银联支付宝:code, sub_code 银联微信:return_code, result_code,err_code 银联二维码平台:respCode 条码前置平台:status、code、result_code、err_code。
以上各种code,仅在银联返回时透传。
格式: |
+| | alipay_infos | | | | 见下alipay_infos参数表 |
+
+
+alipay_infos参数表
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| | total_amount | M | 11 | Price | 交易金额(单位:分, 类型:数字) |
+| | settle_amount | C | 11 | String | 结算币种订单金额 |
+| | pay_amount | C | 11 | String | 支付币种订单金额 |
+| | receipt_amount | M | 11 | String | 实收金额(单位:分, 类型:数字) |
+| | point_amount | C | 11 | Price | 使用集分宝付款的金额 |
+| | invoice_amount | C | 11 | Price | 交易中可给用户开具发票的金额(单位:元) |
+| | fund_bill_list | M | | TradeFundBill[] | 交易支付使用的资金渠道。只有在签约中指定需要返回资金明细,或者入参的query_options 中指定时才返回该字段信息。 |
+| | card_balance | C | 11 | Price | 支付宝卡余额 |
+| | store_name | C | 512 | String | 发生支付交易的商户门店名称 |
+| | discount_goods_detail | C | 1024 | String | 本次交易支付所使用的单品券优惠的商品优惠信息。只有在 query_options中指定时才返回该字段信息。 |
+| | async_payment_mode | C | 20 | String | 异步支付模式,先享后付业务会返回该参 数 , 目 前 有 三 种 值 :ASYNC_DELAY_PAY( 异 步 延 时 付款); ASYNC_REALTIME_PAY( 异步准实时付款); SYNC_DIRECT_PAY(同步直接扣款); |
+| | purchase_merchant_contribute | C | 8 | Price | 如果使用的这张券是用户购买的,则该字段代表用户在购买这张券时商户优惠的金额 |
+| | auth_trade_pay_mode | C | 64 | String | 预授权支付模式,该参数仅在信用预授权支付场景下返回。信用预授权支付:CREDIT_PREAUTH_PAY |
+| | advance_amount | C | 11 | String | 先享后付 2.0 垫资金额,不返回表示没有走垫资,非空表示垫资支付的金额 |
+| | business_params | C | 512 | String | 商户传入业务信息,具体值要和支付宝约定将商户传入信息分发给相应系统,应用于安全,营销等参数直传场景格式为 json 格式 |
+| | buyer_user_type | C | 18 | String | 买家用户类型。 CORPORATE:企业用户;PRIVATE:个人用户。 |
+| | buyer_user_name | C | 128 | String | 买家名称;买家为个人用户时为买家姓名,买家为企业用户时为企业名称; |
+| | mdiscount_amount | C | 11 | String | 商家优惠金额 |
+| | discount_amount | C | 11 | String | 平台优惠金额 |
+| | charge_flags | C | 64 | String | 费率活动标识,当交易享受活动优惠费率时,返回该活动的标识;(1)蓝海活动优惠费率 0,值为 bluesea_1(2) 特 殊 行 业 优 惠 费 率 0 , 值 为industry_special_00(3) 特殊行业优惠费率千一,值为industry_special_01 |
+| | buyer_logon_id | M | 100 | String | 买家支付宝账号 |
+
+
+
+
+##### 订单优惠金额
+微信支付包含商户和微信给的优惠金额,支付宝支付只包含商户给的优惠金额,银联二维码支付只包含商户给的优惠金额
+
+
+
+**业务拓展参数示例**
+
+```json
+"extend_business_params": "{ "
+ extend_params ":{ "
+ sys_service_provider_id ":"
+ 208812333665551 ", "
+ food_order_type ":"
+ home_delivery " } }",
+```
+
+
+
+**银联单品营销请求示例**
+
+```http
+请求地址?amount=100&auth_code=XXXXXXXXXXXXXXXX&goods_detail=
+%7b%22goodsInfo%22%3a%5b%7b%22id%22%3a%2212341234%22%2c%22name%22%3a%22%e6%b5%8b%e8%af%95%e5%95%86%e5%93%81%22%2c%22price%22%3a%22100%22%2c%22quantity%22%3a%221%22%7d%5d%7d
+&merchant_id=XXXXXXXXXX&nonce_str=7aee8b722a614cfa9cfb39ad5409fcdf&service=upload_authcode&third_order_id=UB4C0D38F5091465F920200326100751&
+sign=69fb04df6dda8bfd3110e4891efedc8b
+```
+
+
+
+##### 银联收款方附加数据
+price 和 quantity 字段为数字类型
+
+```json
+银联扫码交易时good_detail示例:
+{
+ "orderInfo" : {
+ "title" :"日用品",
+ "dctAmount" :"10000",
+ "addnInfo" :"屈臣氏(人民广场)店"
+ },
+ "goodsInfo" : [
+ {"id": "1234567890",
+ "name": "商品 1",
+ "price": 500,
+ "quantity": 1
+ },
+ {
+ "id": "1234567891",
+ "name": "商品 2",
+ "price": 1000,
+ "quantity": 2,
+ "category": "类目 1",
+ "addnInfo": "商品图片 http://www.95516.com/xxx.jpg" } ]
+}
+```
+
+注:
+
+1. 银联扫码点餐时,在该域的订单信息 orderInfo 子域中的附加信息 addnInfo 字段需填写该门店对应的品牌标识、门店标识、桌号(其中 SaaS 收银的支付交易需有 品牌标识、门店标识,扫码点餐的支付交易必须有品牌标识、门店标识、桌号)。addnInfo 字段的参考格 式为:{brandId=值&storeId=值&tableNo=值},例如: addnInfo={brandId=AXMX&storeId=12345&tableNo=12}
+2. 银联单品营销时,按照银联需要的内容,在该域的商品信息goodsInfo上送对应的商品信息。
+
+
+
+**注意事项**
+
+(1)所有涉及到金额的单位都位分,币种为RMB,最小为1分,不允许出现小数
+
+(2)文档中参数,标识为必填必须上送(如果缺少会报错),非必填的可填可不填
+
+(3)返回参数中必填为是的参数是一定会返回的,必填为否的参数则不一定返回,因升级或配置等情况实际返回参数可能不会跟文档完全一致,必须以实际接收到的参数为准
+
+
+
+
+
+### 3.扫码支付结果
+#### 3.1、扫码支付结果通知
+**由于诸多因素都会影响到支付结果的通知,推送可能存在延迟,并且不能保证100%推送成功。故强烈建议主接交易查询接口。 **
+
+**POST Content-Type: text/xml; charset=utf-8 **
+
+**通知参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使 用MD5算法) |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 商户号 | merchant_id | M | 10 | string | 乐刷商户号 |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | |
+| 商户订单号 | third_order_id | M | 64 | string | |
+| 订单金额 | amount | M | 无 | string | |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 支付类型 | pay_way | M | 无 | string | [详见下方支付类型](#Mpdey) |
+| 支付时间 | pay_time | M | 无 | string | '2020-09-15 10:11:30' |
+| 银行类型 | bank_type | O | 无 | string | 使用银行卡支付以外的(如零钱)全部展示为others,使用银行卡支付的详见下方[付款银行类型](#cX4pl) |
+| 用户openid | openid | O | 无 | string | |
+| 微信、支付宝等订单号 | out_transaction_id | O | 无 | string | |
+| 用户子标识 | sub_openid | C | 无 | string | 支付成功时才返回。微信:微信公众号APPID 下用户唯一标识;支付宝:买家的支付宝用户ID |
+| 附加数据 | attach | O | 96 | string | 原样返回;注意:只能是汉字、英文字母、数字 |
+| 交易类型 | trade_type | C | 无 | string | 支付成功时才返回:MICROPAY-条码支付,NATIVE-原生扫码支付,JSAPI-公众号支付、服务窗支付,SmPgPay-小程序支付,JSAPIQuick-简易支付 |
+| 通道订单号 | channel_order_id | C | 无 | string | 支付成功时才返回 |
+| 通道订单时间 | channel_datetime | C | 无 | string | 支付成功时才返回 |
+| 支付宝红包金额 | coupon | C | 无 | string | 支付成功时才返回 |
+| 应结算金额 | settlement_amount | C | 无 | string | 实际结算金额,支付成功时才返回 |
+| 折扣优惠金额 | discount_amount | C | 无 | string | 本订单优惠金额,支付成功时才返回 |
+| 优惠详情 | promotion_detail | O | 无 | string | 银联单品的具体优惠详情;微信优惠详情说明:[微信官网](https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1) |
+| 活动标志 | active_flag | O | 无 | string | 活动标志:WXLZ:微信绿洲 ZFBLH:支付宝蓝海 |
+| 买家实付金额 | buyer_pay_amount | O | 无 | String | 微信、支付宝此值有效 |
+| 付款方附加数据 | iss_addn_data | M | 无 | String | 格式如下 |
+| 设备编号 | device_info | O | 32 | string | 上游返回时才返 |
+| 门店编号 | store_id | O | 32 | string | 上游返回时才返 |
+| 通道标记 | channel_flag | O | 32 | string | GXST:高校食堂
PUBWEL:公益
PUBPAY:公缴
ZFBLH:支付宝新蓝海
SLZXY:私立中小幼
INS:保险
ONLINE:线上 |
+| 花呗分期期数 | hb_fq_num | O | 无 | string | 支付宝花呗分期数,一般为3、6、12期,乐刷透传,具体期数由支付宝侧限定 |
+| 支付宝优惠信息 | alipay_infos | | | string | 见下alipay_infos参数表 |
+| 分期信息 | install_info | O | 无 | string | 包含分期笔数(install_nums)/分期付款手续费率(install_rate)/商户补贴手续费率(merchant_fee_subsidy)) |
+
+
+alipay_infos参数表
+
+| **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | :---: | :---: | :---: | --- |
+| total_amount | M | 11 | Price | 交易金额(单位:分, 类型:数字) |
+| point_amount | O | 11 | Price | 积分支付的金额,单位为元,两位小数。该金额代表该笔交易中用户使用积分支付的金额,比如集分宝或者支付宝实时优惠等 |
+| invoice_amount | O | 11 | Price | 交易中用户支付的可开具发票的金额,单位为元,两位小数。该金额代表该笔交易中可以给用户开具发票的金额 |
+| receipt_amount | O | 11 | String | 实收金额(单位:分, 类型:数字) |
+| discount_goods_detail | M | 1024 | String | 本次交易支付所使用的单品券优惠的商品优惠信息。只有在 query_options中指定时才返回该字段信息。 |
+| mdiscount_amount | O | 11 | String | 商家优惠金额 |
+| discount_amount | O | 11 | String | 平台优惠金额 |
+| buyer_logon_id | M | 100 | String | 买家支付宝账号 |
+| fund_bill_list | M | 256 | TradeFundBill[] | 交易支付使用的资金渠道。只有在签约中指定需要返回资金明细,或者入参的query_options 中指定时才返回该字段信息。 |
+
+
+**注意:**
+
+1、支付发起后,乐刷一般30s左右才会返回支付通知,如需快速获取支付结果,请调用“交易结果查询”接口发起查询。
+
+2、支付通知的频率:0s/15s/30s/1m/4m/34m/64m/94m/124m/184m
+
+
+
+##### 支付类型
+| 类型 | 说明 | 状态 |
+| --- | --- | --- |
+| WXZF | 微信 | 支持 |
+| ZFBZF | 支付宝 | 支持 |
+| UPSMPAY | 银联二维码 | 支持 |
+
+
+
+
+**iss_addn_data参考格式:**
+
+| **参数名** | **变量名** | **类型** | **说明** |
+| :---: | :---: | :---: | --- |
+| 商品优惠信息 | dctDetail | String | 商品优惠明细 |
+| 商品编号 | id | String | 参与优惠的商品编号 |
+| 优惠活动编号 | dctId | String | 优惠活动的编号 |
+| 商品优惠数量 | dctQuantity | String | 参与优惠的商品数量 |
+| 商品优惠金额 | dctPrice | String | 商品的优惠总金额(分) |
+
+
+```json
+issAddnData= {
+ "dctDetail" : [{
+ "id": "1234567890",
+ "dctId": "app012345",
+ "dctQuantity": 1",
+ "dctPrice": "500"
+ },{
+ "id": "1234567891",
+ "dctId": "app012345",
+ "dctQuantity": "2",
+ "dctPrice": "1000",
+```
+
+
+
+**返回参数**
+
+| 返回内容 | 说明 |
+| --- | --- |
+| 000000 | 通知成功,乐刷收到此返回后不会继续通知。返回内容000000是string类型,没有双引号。示例:return 000000; |
+| 其他 | 乐刷收到回复或者未收到回复,系统会再次通知。为避免资源浪费,请核实并确保响应信息的准确性,可以是否重复通知为检查手段 |
+
+
+
+
+注意:
+
+1.回调地址为统一下单或条码支付的通知地址。
+
+2.交易回调处理时间为5S内。
+
+3.支付成功才进行推送。
+
+
+
+**付款银行类型**
+
+| 通道 | 说明 |
+| --- | --- |
+| 微信 | [https://pay.weixin.qq.com/wiki/doc/api/mch_bank.php?chapter=4_2](https://pay.weixin.qq.com/wiki/doc/api/mch_bank.php?chapter=4_2) |
+| 支付宝 | [https://alipay.open.taobao.com/doc2/detail?treeId=26&articleId=103259&docType=1](https://alipay.open.taobao.com/doc2/detail?treeId=26&articleId=103259&docType=1) |
+| 银联二维码 | 1 - 借记卡 2- 贷记卡 |
+
+
+#### 3.2、扫码交易结果查询
+
+
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+(4)注:查询时,除非返回明确的支付成功、支付失败、订单关闭等最终状态,其他错误或者未支付状态,都需要再查询,直到得到明确的支付状态。如果超过一段时间还是未支付,可以调用关闭订单接口。
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | query_status(此为固定值) |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | O | 64 | string | 选填 |
+| 乐刷订单号 | leshua_order_id | O | 16 | string | third_order_id和leshua_order_id必填1个,优先使用leshua_order_id |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | C | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 订单金额 | amount | M | 无 | string | |
+| 支付类型 | pay_way | M | 无 | string | [详见下方支付类型](#nlHUH) |
+| 支付完成时间 | pay_time | C | 无 | string | 支付成功时才返回 |
+| 银行类型 | bank_type | O | 无 | string | 使用银行卡支付以外的(如零钱)全部展示为others,使用银行卡支付的详见下方[付款银行类型](#cX4pl) |
+| 用户openid | openid | C | 无 | string | 支付成功时才返回 |
+| 微信、支付宝等订单号 | out_transaction_id | C | 无 | string | 支付成功时才返回 |
+| 用户子标识 | sub_openid | C | 无 | string | 支付成功时才返回。微信:微信公众号APPID下用户唯一标识;支付宝:买家的支付宝用户ID |
+| 附加数据 | attach | O | 96 | string | 支付成功时原样返回;注意:只能是汉字、英文字母、数字 |
+| 交易类型 | trade_type | C | 无 | string | 支付成功时才返回:MICROPAY-条码支付,NATIVE-原生扫码支付,JSAPI-公众号支付、服务窗支付,SmPgPay-小程序支付,JSAPIQuick-简易支付 |
+| 通道订单号 | channel_order_id | C | 无 | string | 支付成功时才返回 |
+| 通道订单时间 | channel_datetime | C | 无 | string | 支付成功时才返回 |
+| 支付宝红包金额 | coupon | C | 无 | string | 支付成功时才返回,单位(分) |
+| 应结算金额 | settlement_amount | C | 无 | string | 实际结算金额,支付成功时才返回 |
+| 折扣优惠金额 | discount_amount | C | 无 | string | 订单优惠金额,支付成功时才返回 |
+| 优惠详情 | promotion_detail | O | 无 | string | 银联单品的具体优惠详情;
微信优惠详情说明:[微信官方文档](https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1) |
+| 活动标志 | active_flag | O | 无 | string | 活动标志。WXLZ:微信绿洲;ZFBLH:支付宝蓝海 |
+| 买家实付金额 | buyer_pay_amount | O | 无 | String | 微信、支付宝此值有效 |
+| 请求耗时 | cost_time | C | 无 | string | 请求接口耗费的时间 |
+| 退款金额
| refund_amount | O | 无 | string | 订单已退款的金额 |
+| 简易支付标识 | simple_url_flag | O | 无 | string | 1表示是简易支付,0表示不是简易支付 |
+| 设备编号 | device_info | O | 32 | string | 上游返回时才返 |
+| 门店编号 | store_id | O | 32 | string | 上游返回时才返 |
+| 支付中间态补充 | interm_state | O | 32 | O | 目前仅针对微信支付,订单为支付中时返回:
NOTPAY,USERPAYING |
+| 通道标记 | channel_flag | O | 32 | string | GXST:高校食堂
PUBWEL:公益
PUBPAY:公缴
ZFBLH:支付宝新蓝海
SLZXY:私立中小幼
INS:保险
ONLINE:线上 |
+| 花呗分期期数 | hb_fq_num | O | 无 | string | 支付宝花呗分期数,一般为3、6、12期,乐刷透传,具体期数由支付宝侧限定 |
+| | alipay_infos | | | | 见下alipay_infos参数表 |
+
+
+alipay_infos参数表
+
+| **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | :---: | :---: | :---: | --- |
+| total_amount | M | 11 | Price | 交易金额(单位:分, 类型:数字) |
+| point_amount | O | 11 | Price | 积分支付的金额,单位为元,两位小数。该金额代表该笔交易中用户使用积分支付的金额,比如集分宝或者支付宝实时优惠等 |
+| invoice_amount | O | 11 | Price | 交易中用户支付的可开具发票的金额,单位为元,两位小数。该金额代表该笔交易中可以给用户开具发票的金额 |
+| receipt_amount | O | 11 | String | 实收金额(单位:分, 类型:数字) |
+| discount_goods_detail | M | 1024 | String | 本次交易支付所使用的单品券优惠的商品优惠信息。只有在 query_options中指定时才返回该字段信息。 |
+| mdiscount_amount | O | 11 | String | 商家优惠金额 |
+| discount_amount | O | 11 | String | 平台优惠金额 |
+| buyer_logon_id | M | 100 | String | 买家支付宝账号 |
+| fund_bill_list | M | 256 | TradeFundBill[] | 交易支付使用的资金渠道。只有在签约中指定需要返回资金明细,或者入参的query_options 中指定时才返回该字段信息。 |
+
+
+
+
+
+
+
+
+**注意事项**
+
+(1)所有涉及到金额的单位都位分,币种为RMB,最小为1分,不允许出现小数
+
+(2)文档中参数,标识为必填必须上送(如果缺少会报错),非必填的可填可不填
+
+(3)返回参数中必填为是的参数是一定会返回的,必填为否的参数则不一定返回,因升级或配置等情况实际返回参数可能不会跟文档完全一致,必须以实际接收到的参数为准
+
+
+
+###
+### 4、扫码退款
+#### 4.1、扫码退款接口
+
+**注意:超过三个月的订单,无法退款请注意
+****一个交易订单号,最多支持发起50次退款**
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+(4)退款一般会返回退款中的状态,如需获取真实退款状态,请调用退款查询接口
+
+(5)每笔支付订单部分退款次数不能超过50次
+
+(6)退款有效期为60天,即订单发起后的60天内可以退款
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | unified_refund 注:此为固定值 |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | O | 64 | string | |
+| 乐刷订单号 | leshua_order_id | O | 32 | string | 商户订单号跟乐刷订单号必填1个,优先使用leshua_order_id |
+| 商户退款单号 | merchant_refund_id | M | 64 | string | 可以包含字母(不能有“_”等特殊字符),确保同一商户下唯一 |
+| 附加数据 | attach | O | 96 | string | 退款成功原样返回;注意:只能是汉字、英文字母、数字 |
+| 退款金额 | refund_amount | M | 10 | string | 退款金额,可做部分退款 |
+| 退款类型 | refund_type | O | 否 | string | 0:不使用账户余额退款,
1:可以使用账户余额退款(优先使用正向交易抵扣,正向交易不够抵扣情况下可用账户余额进行退款)。
2:限定只可以用账户余额进行退款
不传默认不使用账户余额退款 (注意: 实时清分的只能使用账户退款 ) |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串,长度要求32位以内 |
+| 通知地址 | notify_url | O | 128 | string | 接收乐刷退款结果通知的URL,需做Url Encode处理,需要绝对路径,确保乐刷能正确访问 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+返回参数
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | C | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 附加数据 | attach | O | 96 | string | 退款成功原样返回;注意:只能是汉字、英文字母、数字 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| | | | | | |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 退款金额 | refund_amount | M | 无 | string | 退款金额 |
+| 商户退款id | merchant_refund_id | M | 64 | string | |
+| 乐刷退款id | leshua_refund_id | M | 32 | string | |
+| 订单总金额 | total_amount | M | 无 | string | 订单总金额 |
+| 订单余额 | order_balance | M | 无 | string | 订单余额:本次退款后订单剩余金额 |
+| 实际退款金额 | settlement_refund_amount | O | 无 | string | 实际退款金额 |
+| 折扣优惠退款金额 | discount_refund_amount | O | 无 | string | 折扣优惠退款金额 |
+| 退款优惠详情 | refund_detail | O | 无 | string | 退款优惠详情 |
+| 请求耗时 | cost_time | C | 无 | string | 请求接口耗费的时间 |
+
+
+
+
+
+
+
+
+#### 4.2、扫码退款查询
+
+
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+(4)注: 此接口如果查询到退款状态为中间状态时,会同步向上游查询一次退款状态;如果查询到是退款异常情况时,会同步向上游重新发起一次退款请求。
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | unified_query_refund 注:此为固定值 |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | O | 64 | string | |
+| 乐刷订单号 | leshua_order_id | O | 32 | string | 跟third_order_id必填1个 |
+| 商户退款单号 | merchant_refund_id | O | 64 | string | |
+| 乐刷退款单号 | leshua_refund_id | O | 32 | string | 跟merchant_refund_id必填1个 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | C | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0代表成功,非0代表失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 附加数据 | attach | O | 96 | string | 原样返回;注意:只能是汉字、英文字母、数字 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 退款金额 | refund_amount | M | 无 | string | 退款金额 |
+| 商户退款id | merchant_refund_id | M | 64 | string | |
+| 乐刷退款id | leshua_refund_id | M | 32 | string | |
+| 订单总金额 | total_amount | M | 无 | string | |
+| 退款时间 | refund_time | O | 无 | string | 退款成功时间:退款成功才返回 |
+| 实际退款金额 | settlement_refund_amount | O | 无 | string | 实际退款金额 |
+| 折扣优惠退款金额 | discount_refund_amount | O | 无 | string | 折扣优惠退款金额 |
+| 退款优惠详情 | refund_detail | O | 无 | string | 退款优惠详情 |
+| 请求耗时 | cost_time | C | 无 | string | 请求接口耗费的时间 |
+
+
+
+
+
+
+#### 4.3、扫码退款结果通知
+**由于诸多因素都会影响到支付结果的通知,推送可能存在延迟,并且不能保证100%推送成功。故强烈建议主接交易查询接口。**
+
+**通知参数**
+
+| **字段名** | **变量名** | **必填** | **长度限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 订单状态 | status | M | 无 | string | [详见下方订单状态](#aIxZP) |
+| 失败原因 | failure_reason | O | 无 | string | 失败原因 |
+| 附加数据 | attach | O | 96 | string | 原样返回;注意:只能是汉字、英文字母、数字 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 通道商户号 | sub_merchant_id | M | 无 | string | 微信、支付宝、QRC商户号 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 退款金额 | refund_amount | M | 无 | string | 退款金额 |
+| 商户退款id | merchant_refund_id | M | 64 | string | |
+| 乐刷退款id | leshua_refund_id | M | 32 | string | |
+| 订单总金额 | total_amount | M | 无 | string | |
+| 退款时间 | refund_time | C | 无 | string | 退款成功时间:退款成功才返回 |
+| 折扣优惠退款金额 | discount_refund_amount | O | 无 | String | 折扣优惠退款金额 |
+| 实际退款金额 | settlement_refund_amount | O | 无 | String | 实际退款金额 |
+| 退款优惠详情 | refund_detail | O | 无 | String | 退款优惠详情(**在退款成功后才返回**) |
+
+
+
+
+**注意:**
+
+1、发起退款请求后,乐刷一般30s左右才会返回支付通知,如需快速获取支付结果,请调用“退款”接口发起查询。
+
+
+
+**返回参数**
+
+| 返回内容 | 说明 |
+| --- | --- |
+| 000000 | 通知成功,乐刷收到此返回后不会继续通知 |
+| 其他 | 乐刷收到回复或者未收到回复,系统会再次通知。为避免资源浪费,请核实并确保响应信息的准确性,可以是否重复通知为检查手段 |
+
+
+
+
+
+
+### 5、扫码订单关闭接口
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+(4)统一条码支付的订单后15秒后才允许调用订单关闭接口,统一下单订单无此限制。
+(5)银联二维码的不支持关单
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | close_order(此为固定值) |
+| sign_type | sign_type | O | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法;(不上送默认为使用MD5算法) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | O | 64 | string | 选填 |
+| 乐刷订单号 | leshua_order_id | O | 16 | string | third_order_id和leshua_order_id必填1个,优先使用leshua_order_id |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | C | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 用户子标识 | sub_openid | M | 无 | string | |
+| 订单状态 | status | M | 无 | string | |
+| 乐刷订单号 | leshua_order_id | M | 32 | string | 乐刷订单号 |
+| 交易类型 | pay_way | M | 无 | string | [详见下方支付类型](#nlHUH) |
+| 订单金额 | amount | M | 无 | string | |
+| 请求耗时 | cost_time | C | 无 | string | 请求接口耗费的时间 |
+
+
+##### 订单状态
+| **值** | **说明** |
+| :--- | :--- |
+| 0 | 支付中 |
+| 2 | 支付成功 |
+| 6 | 订单关闭 |
+| 8 | 支付失败 |
+| 10 | 退款中 |
+| 11 | 退款成功 |
+| 12 | 退款失败 |
+
+
+
+
+### 6、授权码
+> 授权码相关接口与**条码支付接口**配套使用
+>
+
+#### 6.1、授权码查询用户openid
+****
+
+**请求地址**
+
+(1)/cgi-bin/lepos_pay_gateway.cgi
+
+(2)测试商户信息及请求密钥和回调密钥请联系我们获取。
+
+(3)生产环境走完协议流程并且联调完提交测试报告后,我司运营同事将会提供参数给贵司
+
+(4)注: 此接口需要上送户付款码和对应的微信公众号appid才能查询到用户openid
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | query_openid 注:此为固定值 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 授权码 | auth_code | M | 32 | string | 微信授权码 |
+| 微信appid | appid | M | 32 | string | 微信公众号ID |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | C | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 用户子标识 | sub_openid | M | 无 | string | |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 微信用户标识 | openid | M | 无 | string | 乐刷appid下的用户微信openid |
+
+
+
+
+
+
+#### 6.2、授权码获取银联云闪付用户ID
+
+
+**简要描述**
+
+(1)使用用户授权码换取银联云闪付用户ID,使用此ID发起银联JS支付
+
+**注:** 此步骤的前置条件:与公司归属银联分公司签署协议,并添加域名白名单获取用户授权码。
+
+
+
+**请求参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| :--- | :--- | :--- | --- | --- | --- |
+| 接口名 | service | M | 无 | string | query_userid(此为固定值) |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 用户授权码 | user_auth_code | M | 无 | string | |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 银联支付标识 | app_up_identifier | C | | | 收款方识别HTTP请求User Agent中包含银联支付标识,格式为“UnionPay/<版本号> ”,注意APP标识仅支持字母和数字。云闪付app支付不填,云闪付外app必填。示例:UnionPay/1.0 ICBCeLife |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+
+
+
+
+**返回参数**
+
+| **参数名** | **变量名** | **必填** | **限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 返回状态码 | resp_code | M | 无 | string | 0 - 成功,非0 - 失败。注:此字段是通信标识,业务状态要看result_code |
+| 返回错误信息 | resp_msg | O | 无 | string | 错误描述:resp_code非0时返回 |
+| 业务结果 | result_code | M | 1 | string | 0 - 成功,非0 - 失败 |
+| 错误码 | error_code | O | 无 | string | [参考错误码信息表](#rOC0m) |
+| 错误码描述 | error_msg | O | 无 | string | 错误信息描述 |
+| 商户号 | merchant_id | M | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | M | 64 | string | 商户内部订单号 |
+| 随机字符串 | nonce_str | M | 32 | string | 随机字符串 |
+| 签名 | sign | M | 32 | string | MD5签名结果 |
+| 用户ID | user_id | O | 无 | string | |
+
+
+
+
+
+
+##### 支付类型
+| 类型 | 说明 | 状态 |
+| --- | --- | --- |
+| WXZF | 微信 | 支持 |
+| ZFBZF | 支付宝 | 支持 |
+| UPSMZF | 银联二维码 | 支持 |
+| DCPAY | 数字货币 | 支持 |
+
+
+
+
+##### 订单状态
+| **值** | **说明** |
+| :--- | :--- |
+| 0 | 支付中 |
+| 2 | 支付成功 |
+| 6 | 订单关闭 |
+| 8 | 支付失败 |
+| 10 | 退款中 |
+| 11 | 退款成功 |
+| 12 | 退款失败 |
+
+
+
+
+##### 付款银行类型
+| **通道** | **说明** |
+| --- | --- |
+| 微信 | [https://pay.weixin.qq.com/wiki/doc/api/mch_bank.php?chapter=4_2](https://pay.weixin.qq.com/wiki/doc/api/mch_bank.php?chapter=4_2) |
+| 支付宝 | [https://alipay.open.taobao.com/doc2/detail?treeId=26&articleId=103259&docType=1](https://alipay.open.taobao.com/doc2/detail?treeId=26&articleId=103259&docType=1) |
+| 银联二维码 | 1 - 借记卡 2- 贷记卡 |
+
+
+
+
+##### 业务拓展参数示例(支付宝小程序需传)
+```json
+"extend_business_params": "{ "
+business_params ": {
+ "bizSource": "mAppQrFood",
+ "sourcePath": "pageFoodChain/shopTakeOut/main?suid=10"
+ },
+ "goods_detail": [{
+ "goods_id": "5544",
+ "goods_name": "爽口青笋丝",
+ "price": "0.50",
+ "quantity": 2,
+ "goods_category": "888",
+ "categories_tree": "888",
+ "body": "爽口青笋丝",
+ "show_url": "pageFoodChain/storeDetail/main?suid=10"
+ }], "extend_params": {
+ "sys_service_provider_id": "208812333665551",
+ "food_order_type": "home_delivery"
+ }
+}",
+```
+
+
+
+**条码支付接口goods_detail,按银联单品营销格式传递****参数goodsInfo,格式如下**
+
+
+
+```json
+ "goods_detail":{
+ "goodsInfo" : [
+ {
+ "id": "1234567890",
+ "name": "商品 1",
+ "price": "500",
+ "quantity": "1"},
+ {
+ "id": "1234567891",
+ "name": "商品 2",
+ "price": "1000",
+ "quantity": "2",
+ "category": "类目 1",
+ "addnInfo": "商品图片 http://www.95516.com/xxx.jpg"}]
+ },
+```
+
+
+
+## 7、刷卡及扫码支付异步通知
+
+
+采用HTTP 标准的POST协议(请使用 application/x-www-form-urlencoded 此Content-Type接收通知消息),为了保证数据正确性、准确性,数据必须验证签名。
+
+
+
+**返回数据(支付成功通知如下)**
+
+```xml
+
+ 0
+ 1
+ 0
+ ALIPAYACCOUNT
+
+ 2018-12-07 22:42:39
+ 7551000001201812073279154152
+ 0
+ 0
+
+ 1812072242293655
+ 0000000018
+ 2088032562556921
+ 2018120722001456935441223102
+ 2018-12-07 22:42:39
+ ZFBZF
+ 0
+ 1
+ 0b574d40e722ec76b55d4e8795f71182
+ 2
+
+ 20181207224223102101
+ NATIVE
+
+```
+
+
+
+**返回数据(刷卡支付成功通知如下)**
+
+```xml
+
+0
+600
+000000
+000010
+
+890584058130851
+89147601
+000109
+2203221139307885
+220322393155923079
+2041000394
+6012514015
+20220322114213731
+
+
+113935096395
+2022-03-22 11:41:43
+21e70c91171b8d6ba00dea3c3ef6affa
+218JCA8L7760
+32
+20220322114005352
+220322393155923079
+
+```
+
+
+
+
+
+**返回数据(扫码退款成功通知如下)**
+
+```xml
+
+ 0
+
+ 0
+ 90001401275201
+ 90002391275201
+ 9115219
+ 0000091152192752007041753
+ mccqvx9q0d5nifcsd0uv9xlmkxgr6kdg
+ 2020-07-04 17:53:24
+ 1000
+ 426adb68310b659953d18b629c1a2e7e
+ 11
+ 208860057301617
+ 0000091152192752007041749
+ 5500
+
+```
+
+
+
+### 7.1 扫码支付成功通知
+
+
+(1)通知 URL 是代理商后台配置的通知地址。扫码支付成功后,乐刷会把相关支付信息和用户信息发送到该 URL,商户需要接收处理信息。对后台通知交互时,如果收到商户的应答不是成功或者超时,乐刷认为通知失败,会通过一定的策略定期重新发起通知,尽可能的提高通知的成功率,但是不保证通知最终一定能成功。由于存在重复发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。系统必须能够正确处理重复的通知。
+
+(2)验证签名方法:通知的 error_code、sign 字段不参与签名,签名方式参照数据格式及数据签名说明,其中签名 key 统一由乐刷提供。另外,组织签名串时空值也参与签名。
+
+
+
+**通知参数**
+
+| **字段名** | **变量名** | **必填** | **长度限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 错误码 | error_code | 否 | 无 | string | 参照错误码信息参照表 |
+| sign_type | sign_type | 否 | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法; |
+| 签名 | sign | 是 | 32 | string | MD5 签名结果 |
+| 商户号 | merchant_id | 是 | 10 | string | 乐刷商户号 |
+| 乐刷订单号 | leshua_order_id | 是 | 32 | string | |
+| 商户订单号 | third_order_id | 是 | 64 | string | |
+| 订单金额 | amount | 是 | 无 | string | |
+| 订单状态 | status | 是 | 无 | string | 见下方[订单的状态](#CozIx) |
+| 支付类型 | pay_way | 是 | 无 | string | 见下方[支付类型](#yGR0s) |
+| 支付时间 | pay_time | 是 | 无 | string | '2018-08-20 19:19:19' |
+| 银行类型 | bank_type | 否 | 无 | string | |
+| 用户openid | openid | 否 | 无 | string | |
+| 微信、支付宝等订单号 | out_transaction_id | 否 | 无 | string | |
+| 用户子标识 | sub_openid | 否 | 无 | string | 支付成功时才返回。微信:子商户appid 下用户唯一标识;支付宝:买家的支付宝用户id; |
+| 附加数据 | attach | 否 | 96 | string | 支付成功时才返回。原样返回 |
+| 交易类型 | trade_type | 否 | 无 | string | 支付成功时才返回。(1)MICROPAY--刷卡支付/条码支付(2)NATIVE--原生扫码支付(3)JSAPI--公众号支付/服务窗支付(4)APP--app支付(5)H5Pay-支付支付(6)SmPgPay-小程序支付(7)JSAPIQuick-简易支付 |
+| 通道订单号 | channel_order_id | 否 | 无 | string | 支付成功时才返回 |
+| 通道订单时间 | channel_datetime | 否 | 无 | string | 支付成功时才返回 |
+| 支付宝红包金额 | coupon | 否 | 无 | string | 支付成功时才返回,单位:分 |
+| 应结算金额 | settlement_amount | 否 | 无 | string | 实际结算金额,支付成功时才返回,单位:分 |
+| 折扣优惠金额 | discount_amount | 否 | 无 | string | 本订单优惠金额,支付成功时才返回,单位:分 |
+| 优惠详情 | promotion_detail | 否 | 无 | string | 优惠详情:[微信官网](https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1) |
+| 活动标志 | active_flag | 否 | 无 | string | 活动标志:WXLZ:微信绿洲,ZFBLH:支付宝蓝海 |
+| **商户终端编号** | pos_no | 否 | 60 | string | 只能是汉字、英文字母、数字 注意:银联类型交易时,只能 8位:数字字母 不支持 特殊字符 |
+
+
+
+
+**返回参数**
+
+| **字段名** | **说明** |
+| --- | --- |
+| 000000 | 通知成功,乐刷收到此返回后不会继续通知 |
+| 其他 | 乐刷收到回复或者未收到回复,系统会再次通知。为避免资源浪费,请核实并确保响应信息的准确性,可以是否重复通知为检查手段。 |
+
+
+
+
+##### 支付类型
+| **类型** | **说明** | **状态** |
+| --- | --- | --- |
+| WXZF | 微信 | 支持 |
+| ZFBZF | 支付宝 | 支持 |
+| UPSMZF | 银联二维码 | 支持 |
+| QQZF | QQ | 支持 |
+| POS | 刷卡 | 支持 |
+| DCPAY | 数字货币 | 支持 |
+| UPSMPAY | 银联二维码(回调时返回) | 支持 |
+
+
+
+
+##### 订单状态值
+| **值** | **说明** |
+| --- | --- |
+| 0 | 支付中 |
+| 2 | 支付成功 |
+| 6 | 订单关闭 |
+| 8 | 支付失败 |
+| 10 | 退款中 |
+| 11 | 退款成功 |
+| 12 | 退款失败 |
+| 30 | 刷卡支付成功 |
+| 31 | 刷卡撤销成功 |
+| 32 | 刷卡退货成功 |
+| 33 | 刷卡冲正成功 |
+
+
+
+
+### 7.2 扫码退款通知
+
+
+(1)通知 URL 与扫码支付成功通知一样,均为代理商后台配置的通知地址。扫码交易退款时、退款成功时、退款失败时,乐刷均会把相关退款信息发送到该 URL,商户需要接收处理信息。对后台通知交互时,如果收到商户的应答不是成功或者超时,乐刷认为通知失败,会通过一定的策略定期重新发起通知,尽可能的提高通知的成功率,但是不保证通知最终一定能成功。由于存在重复发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。系统必须能够正确处理重复的通知。
+
+(2)验证签名方法:通知的 error_code、sign 字段不参与签名,签名方式参照第 3 章 数据签名,其中签名 key 统一由乐刷提供。另外,组织签名串时空值也参与签名。
+
+
+
+**通知参数**
+
+| **字段名** | **变量名** | **必填** | **长度限制** | **类型** | **说明** |
+| --- | --- | --- | --- | --- | --- |
+| 签名 | sign | 是 | 32 | string | MD5 签名结果 |
+| sign_type | sign_type | 否 | 10 | string | 接口签名类型::MD5/SM3。 支持MD5和国密SM3算法 |
+| 订单状态 | status | 是 | 无 | string | 见下方[订单状态](#yP5Xo) |
+| 失败原因 | failure_reason | 否 | 无 | string | 失败原因 |
+| 商户号 | merchant_id | 是 | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | 是 | 64 | string | 商户内部订单号 |
+| 乐刷订单号 | leshua_order_id | 是 | 32 | string | 乐刷订单号 |
+| 退款金额 | refund_amount | 是 | 无 | string | 退款金额(分) |
+| 商户退款 id | merchant_refund_id | 是 | 64 | string | |
+| 乐刷退款 id | leshua_refund_id | 是 | 32 | string | |
+| 订单总金额 | total_amount | 是 | 无 | string | |
+| 退款时间 | refund_time | 否 | 无 | string | 退款成功时间-退款成功才返回 |
+
+
+
+
+**返回参数**
+
+| **字段名** | **变量名** |
+| --- | --- |
+| 000000 | 通知成功,乐刷收到此返回后不会继续通知 |
+| 其他 | 乐刷收到回复或者未收到回复,系统会再次通知 |
+
+
+
+
+##### 订单状态
+| **值** | **说明** |
+| --- | --- |
+| 0 | 支付中 |
+| 2 | 支付成功 |
+| 6 | 订单关闭 |
+| 8 | 支付失败 |
+| 10 | 退款中 |
+| 11 | 退款成功 |
+| 12 | 退款失败 |
+| 30 | 刷卡支付成功 |
+| 31 | 刷卡撤销成功 |
+| 32 | 刷卡退货成功 |
+| 33 | 刷卡冲正成功 |
+
+
+
+
+### 7.3 刷卡交易通知
+
+
+(1)通知 URL 与扫码支付成功通知一样,均为代理商后台配置的通知地址。刷卡交易成功时、刷卡撤销成功时、刷卡退货成功时、刷卡冲正成功时,乐刷均会把相关交易信息发送到该 URL,商户需要接收处理信息。对后台通知交互时,如果收到商户的应答不是成功或者超时,乐刷认为通知失败,会通过一定的策略定期重新发起通知,尽可能的提高通知的成功率,但是不保证通知最终一定能成功。由于存在重复发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。系统必须能够正确处理重复的通知。
+
+(2)验证签名方法:通知的 error_code、sign 字段不参与签名,签名方式参照第 3 章 数据签名,其中签名 key 统一由乐刷提供。另外,组织签名串时空值也参与签名。
+
+(3)境外卡统一按照贷记卡费率进行结算,所以返回2
+
+
+
+**通知参数**
+
+| **字段名** | **变量名** | **必填** | **长度限制** | **类型** | **说明** |
+| :---: | :---: | :---: | :---: | :---: | :---: |
+| 签名 | sign | 是 | 32 | string | MD5 签名结果 |
+| 订单状态 | status | 是 | 无 | string | 详见下方[订单状态](#p7QuH) |
+| 结算类型 | T0 | 是 | 无 | string | |
+| 设备SN号 | sn | 是 | 无 | string | 硬件序列号和机身上一致 |
+| 授权码 | authorize_code | 是 | 6 | string | 普通交易下返回000000 预授权交易不固定 |
+| 失败原因 | failure_reason | 否 | 无 | string | 失败原因 |
+| 商户号 | merchant_id | 是 | 10 | string | 由乐刷分配 |
+| 商户订单号 | third_order_id | 是 | 64 | string | 商户内部订单号
退货时,返回原订单的第三方订单号 |
+| 乐刷订单号 | leshua_order_id | 是 | 32 | string | 乐刷订单号
退货时,返回原订单的乐刷订单号 |
+| 交易金额 | amount | 是 | 无 | string | 交易金额(分) |
+| 银行卡号 | card_id | 否 | 无 | string | 刷卡交易时提供 |
+| 卡类型 | card_type | 否 | 1 | string | 1----借记卡
2----贷记卡 3---- 准贷记 |
+| 发行主体 | pan_overseas | 否 | 1 | string | 0----境内卡 1----境外卡 |
+| 结算方式 | pan_type | 否 | 1 | string | (1使用商户借记卡费率,非1使用商户贷记卡费率 ) 0-----未知 1-----借记 2-----贷记 3-----准贷记 4-----借贷合一 5-----预付费 6-----半开放预付费 |
+| 发卡行 | bank_name | 否 | 无 | string | 刷卡交易时提供 |
+| 刷卡pos批次号 | batch_no | 是 | 无 | string | 每次签到后从后台获取批次号,当批交易均上送此批次号 |
+| 刷卡pos流水号 | flow_id | 是 | 3 | string | 终端为每个交易随机生成的流水号,随交易信息上送 |
+| 乐刷SN号 | leshua_sn | 是 | 无 | string | 刷卡交易时提供 |
+| 刷卡pos参考号 | reference_number | 是 | 32 | string | POS中心分配的流水号,作为对账参考号 |
+| 银联商户号 | cups_merchant_id | 否 | 20 | string | 表示上送银联的商户编号 |
+| 银联终端号 | cups_terminal_id | 否 | 8 | string | 表示上送银联的终端编号 |
+| 交易流水号 | transaction_id | 否 | 18 | string | 用于表示此操作的流水号 |
+| 刷卡交易时间 | pay_time | 否 | 无 | string | 刷卡交易时提供 |
+| 消费撤销时间 | refund_time | 否 | 无 | string | 消费撤销时提供 |
+| 消费退货时间 | returngoods_time | 否 | 无 | string | 消费退货时提供 |
+| 消费冲正时间 | reverse_time | 否 | 无 | string | 消费冲正时提供 |
+| 商户撤销id | merchant_refund_id | 否 | 无 | string | 消费撤销时提供
第三方传入的撤销订单号 |
+| 商户退货id | merchant_returngoods_id | 否 | 无 | string | 消费退货时提供
第三方传入的退货订单号 |
+| 乐刷退款id | leshua_refund_id | 否 | 18 | string | 消费退货时提供
乐刷生成的退货流水号 |
+| 商户冲正id | merchant_reverse_id | 否 | 无 | string | 消费冲正时提供
第三方传入的冲正订单号 |
+| 到账标识 | t0 | 否 | 1 | String | 0:表示t1到账 1:表示t0到账; 刷卡交易时提供 |
+
+
+
+
+**返回参数**
+
+| **字段名** | **变量名** |
+| --- | --- |
+| 000000 | 通知成功,乐刷收到此返回后不会继续通知 |
+| 其他 | 乐刷收到回复或者未收到回复,系统会再次通知 |
+
+
+
+
+##### 订单状态
+| **值** | **说明** |
+| --- | --- |
+| 30 | 刷卡支付成功 |
+| 31 | 刷卡撤销成功 |
+| 32 | 刷卡退货成功 |
+| 33 | 刷卡冲正成功 |
+| 41 | 预授权成功 |
+| 43 | 预授权撤销成功 |
+| 45 | 预授权完成(请求)成功 |
+| 47 | 预授权完成(通知)成功 |
+| 49 | 预授权完成撤销成功 |
+
+
+### 7.4 刷卡交易查询
+
+
+请求地址:/agentCardTransaction/cardFlowQuery
+
+加密规则: md5hex(代理商密钥+reqSerialNo+version+ data的 json 串)
+
+
+
+**请求参数:**
+
+| 名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
+| --- | --- | --- | --- | --- | --- |
+| version | string | 必须 | | 版本号 | |
+| agentId | string | 必须 | | 代理商编号 | |
+| sign | string | 必须 | | 验签值 | |
+| reqSerialNo | string | 必须 | | 随机字符串,一般为一个和日期有关的随机数 | |
+| data | object | 非必须 | | | |
+| └merchantId | string | 必须 | | 商户号 | |
+| └operation | string | 必须 | | 操作类型(query_by_order,query_by_transaction,query_by_third_order)) | |
+| └orderId | string | 非必须 | | 订单编号 | |
+| └transactionId | string | 非必须 | | 交易单号 | |
+| └thirdOrderId | string | 非必须 | | 第三方订单号 | |
+
+
+**返回参数:**
+
+| 名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
+| --- | --- | --- | --- | --- | --- |
+| traceId | string | 必须 | | 请求序列号 | |
+| code | integer | 必须 | | 错误码 | |
+| message | string | 必须 | | 错误信息 | |
+| data | object | 非必须 | | | |
+| └orderId | string | 非必须 | | 乐刷订单号 | |
+| └errorCode | integer | 非必须 | | 请求错误码,成功为0 | |
+| └errorMsg | string | 非必须 | | 错误提示信息,成功时值为空 | |
+| └thirdOrderId | string | 非必须 | | 商户内部订单号 | |
+| └merchantId | string | 非必须 | | 乐刷商户号 | |
+| └amount | integer | 非必须 | | 交易金额 | |
+| └orderStatus | integer | 非必须 | | 订单状态,0-初始状态(可能交易失败);5-交易成功;11-交易失败;53-交易失败(冲正成功);54-交易结果未知(冲正失败);3-退款成功;32-退款失败;33-退款状态未知;4-退货成功;41-退货失败;42-退货状态未知 | |
+| └batchNo | string | 非必须 | | POS交易批次号 | |
+| └flowNo | string | 非必须 | | POS交易流水号 | |
+| └sign | string | 非必须 | | 签名 | |
+| └merchantName | string | 非必须 | | 乐刷商户名称 | |
+| transactionsInfo | object [] | 非必须 | | 流水 | item 类型: object |
+| └merchantId | string | 非必须 | | 乐刷商户号 | |
+| └pinpadUuid | string | 非必须 | | 乐刷SN | |
+| └channelMerchantId | string | 非必须 | | 通道商户号 | |
+| └channelTerminalId | string | 非必须 | | 通道终端号 | |
+| └operationType | integer | 非必须 | | 操作类型,与订单状态一致 | |
+| └inputType | string | 非必须 | | 交易用卡方式:051-插卡有密交易;052-插卡无密交易;071-挥卡有密交易;072-挥卡无密交易; | |
+| └cardBank | string | 非必须 | | 发卡行名称 | |
+| └authorizeCode | string | 非必须 | | 交易授权码 | |
+| └referenceNo | string | 非必须 | | 交易参考号 | |
+| └cardId | string | 非必须 | | 交易卡号 | |
+| └pinpadSn | string | 非必须 | | 机具终端硬件号TUSN | |
+| └time | string | 非必须 | | 交易时间 | |
+| └cardType | integer | 非必须 | | 卡类型:0(借记卡),2(贷记卡) | |
+| └channelBatchNo | string | 非必须 | | 通道交易批次号 | |
+| └channelFlowNo | string | 非必须 | | 通道交易流水号 | |
+| └transactionId | string | 非必须 | | 乐刷流水号 | |
+| └channelId | string | 非必须 | | 通道id | |
+| └channelMerchantName | string | 非必须 | | 通道商户名称 | |
+| └amount | string | 非必须 | | 流水金额 | |
+
+
+### 8、交易错误码信息参照表
+
+
+| **错误码** | **描述** |
+| :---: | :---: |
+| -20001 | 参数错误或无效 |
+| -20002 | 无效的乐刷商户号 |
+| -20003 | 商户订单号格式有误 |
+| -20004 | 乐刷订单不存在 |
+| -20005 | 服务错误 |
+| -20006 | 验签失败 |
+| -20007 | 签名 Key 未配置 |
+| -20008 | 支付类型错误 |
+| -20009 | 订单金额填写有误 |
+| -20010 | 系统错误 |
+| -20011 | 非法参数 |
+| -20012 | 授权码为空 |
+| -20013 | 非法的授权码 |
+| -20014 | 未知类型的授权码 |
+| -20015 | 非法的公众号支付标识 |
+| -20016 | 无效乐刷订单号 |
+| -20018 | 无效的第三方订单号或者乐刷订单号 |
+| -20019 | 订单状态不允许退款 |
+| -20020 | 订单未退款 |
+| -20021 | 用户名跟商户ID不匹配 |
+| -20022 | 无效的第三方退款订单号 |
+| -20023 | 订单可退余额不足 |
+| -20024 | 乐刷或第三方订单号必填 1 个 |
+| -20025 | 乐刷或第三方退款订单号必填 1 个 |
+| -20026 | 第三方订单号在该商户号下已经存在 |
+| -20027 | 该订单已支付 |
+| -20028 | 订单支付失败,不能撤销 |
+| -20029 | 该订单已退款 |
+| -20030 | 该订单退款失败,不能撤销 |
+| -20031 | 无效的机具 SN 编号,请联系客服 |
+| -20032 | 机具 SN 跟商户无绑定关系 |
+| -4027 | 系统异常 |
+| -4006 | 订单不存在 |
+| -1006 | 该订单号已被用 |
+| -1002 | 无效商户号 |
+| -2034 | 测试商户号金额限制 |
+| -4004 | 订单正在处理中 |
+| -5103 | 商户退款 id 已存在 |
+| -5014 | 商户无退款权限 |
+| -5015 | 暂不支持退款 |
+| -5016 | 订单状态异常 |
+| -5017 | 订单可退金额不足 |
+| -5018 | 订单退款次数超限 |
+| -5019 | 订单未发起退款 |
+| -5020 | 接口不支持该功能 |
+| -2125 | 交易被风控拦截 |
+
+
+| -5035 | 下单异常,可能原因有通道网络异常,通道状态异常,通道商户异常等 |
+| :---: | :---: |
+
+
+以实际返回的错误提示(error_msg)为准
diff --git a/docs/乐刷支付接入文档.md b/docs/乐刷支付接入文档.md
index e174605..c5b4223 100644
--- a/docs/乐刷支付接入文档.md
+++ b/docs/乐刷支付接入文档.md
@@ -44,7 +44,8 @@ MD5 签名步骤:
- 请求签名:一般不包含 `sign` 本身。
- 应答验签:按乐刷返回参数验签,实际返回字段可能因升级增加,验签时要允许新增字段。
-- 支付/退款通知验签:`error_code` 和 `sign` 不参与签名,空值参与签名,密钥使用乐刷提供的通知验签密钥。当前实现为 `LESHUA_NOTIFY_KEY`,为空时回退 `LESHUA_SIGN_KEY`。
+- 支付/退款通知验签:`error_code`、`leshua` 和 `sign` 不参与签名,其他返回字段按原样参与;空值参与签名;密钥只使用乐刷提供的通知验签密钥 `LESHUA_NOTIFY_KEY`。实测通知携带 `sign_type=MD5`,按普通返回字段参与签名。
+- 乐刷 XML 通知里的空标签也属于空值参数,必须保留并参与签名,例如 `` 应进入待签名串为 `goods_tag=`。
- `sign_type=SM3` 时签名结果为 64 位;不上传 `sign_type` 默认 MD5。
## 统一下单
diff --git a/frontend/src/views/account/WalletView.vue b/frontend/src/views/account/WalletView.vue
index e25a293..79135ab 100644
--- a/frontend/src/views/account/WalletView.vue
+++ b/frontend/src/views/account/WalletView.vue
@@ -1,5 +1,5 @@