pay.go 37.2 KB
Newer Older
wangp's avatar
wangp committed
1 2 3 4 5 6 7
package pay

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
wangp's avatar
wangp committed
8
	"database/sql"
wangp's avatar
wangp committed
9 10 11 12 13 14
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/astaxie/beego/httplib"
wangp's avatar
wangp committed
15
	uID "github.com/satori/go.uuid"
wangp's avatar
wangp committed
16
	"io/ioutil"
wangp's avatar
wangp committed
17 18
	rand2 "math/rand"
	"strconv"
wangp's avatar
wangp committed
19 20
	"strings"
	"system_pay/models"
21
	"system_pay/mysql"
wangp's avatar
wangp committed
22
	"system_pay/setting"
wangp's avatar
wangp committed
23
	"time"
wangp's avatar
wangp committed
24 25 26
)

// 拉卡拉支付
wangp's avatar
wangp committed
27
func UnifiedOrder(input *models.PlaceAnOrderParamInput, ip string) (interface{}, error) {
wangp's avatar
wangp committed
28
	//输入项check
wangp's avatar
wangp committed
29 30 31
	if input.SourceCode==0 {
		return nil, errors.New("输入项「source_code」为空错误")
	}
wangp's avatar
wangp committed
32 33 34
	if input.PlatformType==0 {
		return nil, errors.New("输入项「platform_type」为空错误")
	}
wangp's avatar
wangp committed
35

wangp's avatar
wangp committed
36
	fmt.Println("谛宝多多输入参数")
wangp's avatar
wangp committed
37 38
	fmt.Println(input)

wangp's avatar
wangp committed
39 40 41 42 43 44 45 46 47 48
	orderID := GetUID()

	attachMap := make(map[string]interface{}, 0)
	attachMap["store_sn"] = input.StoreSn
	attachMap["old_attach"] = input.AttachInfo

	attach, _ := json.Marshal(attachMap)
	input.AttachInfo = string(attach)

	// 插入数据库
wangp's avatar
wangp committed
49
	db, err := mysql.NewPayConn()
wangp's avatar
wangp committed
50 51 52 53 54 55 56 57 58
	if err != nil {
		return 0, err
	}

	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}

wangp's avatar
wangp committed
59
	defer mysql.CloseTx(tx, err)
wangp's avatar
wangp committed
60 61 62

	billID, err := InsertPayBill(tx, input, orderID)
	if err != nil {
wangp's avatar
wangp committed
63
		tx.Rollback()
wangp's avatar
wangp committed
64 65 66
		return nil, err
	}

wangp's avatar
wangp committed
67
	//数据重组 - start
wangp's avatar
wangp committed
68 69 70 71
	now := time.Now()
	now.Add(time.Minute * 60)
	date_time1 := now.Format("20060102150405")
	date_time2 := now.Add(time.Minute * 60).Format("20060102150405")
wangp's avatar
wangp committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

	var version, out_org_code, merchant_no1, merchant_no2, merchant_no3, term_no3, merchant_no4, term_no4 string
	//平台类型 1:saas 2:shop 3:shop mobile 4:收银台 6:bk_shop 7:bk_shop_mobile
	if input.PlatformType==2 || input.PlatformType==3 {
		// 谛宝多多自营
		version = setting.Conf.Lakala.DbcVersion
		out_org_code = setting.Conf.Lakala.DbcAppid
		merchant_no1 = setting.Conf.Lakala.DbcMerchantNo1
		merchant_no2 = setting.Conf.Lakala.DbcMerchantNo2
		merchant_no3 = setting.Conf.Lakala.DbcMerchantNo3
		term_no3 = setting.Conf.Lakala.DbcTermNo3
		merchant_no4 = setting.Conf.Lakala.DbcMerchantNo4
		term_no4 = setting.Conf.Lakala.DbcTermNo4
	} else if input.PlatformType==6 || input.PlatformType==7 {
		// 必康自营
		version = setting.Conf.Lakala.BkVersion
		out_org_code = setting.Conf.Lakala.BkAppid
		merchant_no1 = setting.Conf.Lakala.BkMerchantNo1
		merchant_no2 = setting.Conf.Lakala.BkMerchantNo2
		merchant_no3 = setting.Conf.Lakala.BkMerchantNo3
		term_no3 = setting.Conf.Lakala.BkTermNo3
		merchant_no4 = setting.Conf.Lakala.BkMerchantNo4
		term_no4 = setting.Conf.Lakala.BkTermNo4
	} else {
		// 必康医生
		version = setting.Conf.Lakala.SaasVersion
		out_org_code = setting.Conf.Lakala.SaasAppid
		merchant_no1 = setting.Conf.Lakala.SaasMerchantNo1
		merchant_no2 = setting.Conf.Lakala.SaasMerchantNo2
		merchant_no3 = setting.Conf.Lakala.SaasMerchantNo3
		term_no3 = setting.Conf.Lakala.SaasTermNo3
		merchant_no4 = setting.Conf.Lakala.SaasMerchantNo4
		term_no4 = setting.Conf.Lakala.SaasTermNo4
	}
wangp's avatar
wangp committed
106 107 108 109 110 111 112

	var url string
	data := make(map[string]interface{}) //数据结构
	data["req_time"] = date_time1
	data["version"] = version
	data["out_org_code"] = out_org_code

wangp's avatar
wangp committed
113 114
	//source_code 1: 微信 Native 2:微信小程序 3:微信内支付 4:h5 跳微信
	//5:支付宝(web)-扫码或登录支付宝账户 6:alipay(mobile) 7:alipay(app)
wangp's avatar
wangp committed
115 116
	//9: B2C 10:bk支付宝web 11:bk 支付宝手机 15:快捷支付(银行卡)
	//16:微信小程序-必康自营 17:微信JASPI-必康自营
wangp's avatar
wangp committed
117
	if input.SourceCode==4 || input.SourceCode==6 ||input.SourceCode==1 ||
wangp's avatar
wangp committed
118 119
		input.SourceCode==5 || input.SourceCode==15 ||
		input.SourceCode==16 || input.SourceCode==17 {
wangp's avatar
wangp committed
120
		//聚合收银台(微信H5、支付宝H5、微信扫码、支付宝扫码)
wangp's avatar
wangp committed
121
		//聚合收银台(快捷支付(银行卡))
wangp's avatar
wangp committed
122
		//聚合收银台(微信小程序-必康自营)
wangp's avatar
wangp committed
123
		url = setting.Conf.Lakala.UrlCreate //聚合收银台
wangp's avatar
wangp committed
124 125 126 127 128

		// 构造回调url
		input.NoticeURL = GetNoticeURL(input.SourceCode)

		data2 := make(map[string]interface{})
wangp's avatar
wangp committed
129
		if input.SourceCode==4 || input.SourceCode==6 {
wangp's avatar
wangp committed
130
			data2["merchant_no"] = merchant_no1 //微信H5、支付宝H5
wangp's avatar
wangp committed
131
		} else {
wangp's avatar
wangp committed
132
			data2["merchant_no"] = merchant_no2 //其它
wangp's avatar
wangp committed
133
		}
wangp's avatar
wangp committed
134 135 136
		data2["total_amount"] = input.GoodsPrice*100
		data2["out_order_no"] = orderID //随机生成的订单号 //商户订单号

wangp's avatar
wangp committed
137 138 139
		if input.SourceCode==15 {
			//快捷支付
			data2["counter_param"] = "{\"pay_mode\":\"QUICK_PAY\"}"
wangp's avatar
wangp committed
140 141 142 143 144
			if input.AuthCodes != "" {
				//LAKALA签约协议号列表
				auth_codes := strings.Split(input.AuthCodes, ",")
				data2["sgn_info"] = auth_codes //签约协议号列表(字符串)
			}
wangp's avatar
wangp committed
145
		} else if input.SourceCode < 5 || input.SourceCode==16 || input.SourceCode==17 {
wangp's avatar
wangp committed
146 147 148 149 150 151
			//微信
			data2["counter_param"] = "{\"pay_mode\":\"WECHAT\"}"
		} else {
			//支付宝
			data2["counter_param"] = "{\"pay_mode\":\"ALIPAY\"}"
		}
wangp's avatar
wangp committed
152

wangp's avatar
wangp committed
153
		data2["order_efficient_time"] = date_time2 //订单有效期 格式yyyyMMddHHmmss,最大支持下单时间+2天
wangp's avatar
wangp committed
154 155 156 157 158
		data2["notify_url"] = input.NoticeURL      //订单支付成功后商户接收订单通知的地址 http://xxx.xxx.com
		data2["callback_url"] = input.ReturnURL    //客户端下单完成支付后返回的商户网页跳转地址
		data2["order_info"] = input.PlatformInfo   //订单标题,在使用收银台扫码支付时必输入,交易时送往账户端
		//data2["goods_mark"] = input.AttachInfo   //商品信息标识 (1:含商品信息,不填默认不含商品信息)
		data2["support_refund"] = 1                //是否支持退款 默认0 不支持
wangp's avatar
wangp committed
159 160 161 162 163 164

		data["req_data"] = make(map[string]interface{})
		data["req_data"] = data2

	} else if input.SourceCode==2 || input.SourceCode==3 {
		//聚合主扫(微信JSAPI、微信小程序)
wangp's avatar
wangp committed
165
		url = setting.Conf.Lakala.UrlPreorder //聚合主扫
wangp's avatar
wangp committed
166 167 168 169 170

		// 构造回调url
		input.NoticeURL = GetNoticeURL(input.SourceCode)

		data2 := make(map[string]interface{})
wangp's avatar
wangp committed
171 172
		data2["merchant_no"] = merchant_no3
		data2["term_no"] = term_no3
wangp's avatar
wangp committed
173 174 175
		data2["total_amount"] = input.GoodsPrice*100
		data2["out_trade_no"] = orderID //随机生成的订单号 //商户交易流水号

wangp's avatar
wangp committed
176
		//data2["order_efficient_time"] = date_time2 //订单有效期 格式yyyyMMddHHmmss,最大支持下单时间+2天
wangp's avatar
wangp committed
177
		data2["notify_url"] = input.NoticeURL      //订单支付成功后商户接收订单通知的地址 http://xxx.xxx.com
wangp's avatar
wangp committed
178 179
		//data2["callback_url"] = input.ReturnURL    //客户端下单完成支付后返回的商户网页跳转地址
		data2["subject"] = input.PlatformInfo   //订单标题,在使用收银台扫码支付时必输入,交易时送往账户端
wangp's avatar
wangp committed
180
		//data2["goods_mark"] = input.AttachInfo   //商品信息标识 (1:含商品信息,不填默认不含商品信息)
wangp's avatar
wangp committed
181

wangp's avatar
wangp committed
182 183
		//微信JSAPI、微信小程序
		data2["account_type"] = "WECHAT" //钱包类型
wangp's avatar
wangp committed
184 185 186 187 188
		if input.SourceCode==2 {
			data2["trans_type"] = "71" //接入方式:微信小程序
		} else {
			data2["trans_type"] = "51" //接入方式:微信JSAPI
		}
wangp's avatar
wangp committed
189

wangp's avatar
wangp committed
190 191 192 193 194
		//地址位置信息
		data3 := make(map[string]interface{})
		data3["request_ip"] = ip
		data2["location_info"] = make(map[string]interface{})
		data2["location_info"] = data3
wangp's avatar
wangp committed
195

wangp's avatar
wangp committed
196 197
		//地址位置信息
		data4 := make(map[string]interface{})
wangp's avatar
wangp committed
198
		data4["sub_appid"] = input.AppID //子商户公众账号ID
wangp's avatar
wangp committed
199
		data4["user_id"] = input.OpenID //用户标识(sub_openid)
wangp's avatar
wangp committed
200

wangp's avatar
wangp committed
201 202
		data2["acc_busi_fields"] = make(map[string]interface{})
		data2["acc_busi_fields"] = data4
wangp's avatar
wangp committed
203

wangp's avatar
wangp committed
204 205
		data["req_data"] = make(map[string]interface{})
		data["req_data"] = data2
wangp's avatar
wangp committed
206

wangp's avatar
wangp committed
207
	} else if input.SourceCode==9 {
wangp's avatar
wangp committed
208
		//聚合被扫(扫码枪)
wangp's avatar
wangp committed
209
		if input.DynamicID=="" {
wangp's avatar
wangp committed
210
			tx.Rollback()
wangp's avatar
wangp committed
211 212 213
			return nil, errors.New("输入项「dynamic_id」为空错误")
		}

wangp's avatar
wangp committed
214
		url = setting.Conf.Lakala.UrlMicropay //聚合被扫
wangp's avatar
wangp committed
215 216

		data2 := make(map[string]interface{})
wangp's avatar
wangp committed
217 218
		data2["merchant_no"] = merchant_no4
		data2["term_no"] = term_no4
wangp's avatar
wangp committed
219 220 221 222
		data2["out_trade_no"] = orderID //随机生成的订单号 //商户交易流水号
		//扫码支付授权码,设备读取用户APP中的条码或者二维码信息,用户付款码条形码规则见说明
		data2["auth_code"] = input.DynamicID
		data2["total_amount"] = input.GoodsPrice*100
wangp's avatar
wangp committed
223

wangp's avatar
wangp committed
224 225 226 227 228 229 230 231 232 233
		data3 := make(map[string]interface{})
		data3["request_ip"] = ip
		//data3["location"] = "+37.123456789,-121.123456789"
		data2["location_info"] = make(map[string]interface{})
		data2["location_info"] = data3

		data["req_data"] = make(map[string]interface{})
		data["req_data"] = data2

	} else {
wangp's avatar
wangp committed
234
		tx.Rollback()
wangp's avatar
wangp committed
235
		return nil, errors.New("输入参数「source_code」错误,有效值为[1-6,9,15-17]")
wangp's avatar
wangp committed
236
	}
wangp's avatar
wangp committed
237 238 239
	//数据重组 - end
	fmt.Println("拉卡拉输入参数")
	fmt.Println(data)
wangp's avatar
wangp committed
240 241
	fmt.Println("拉卡拉接口url")
	fmt.Println(url)
wangp's avatar
wangp committed
242

wangp's avatar
wangp committed
243 244 245
	// 插入下单请求参数
	err = InsertPayBillDetailRequestBody(tx, billID, data)
	if err != nil {
wangp's avatar
wangp committed
246
		tx.Rollback()
wangp's avatar
wangp committed
247 248 249
		return nil, err
	}

wangp's avatar
wangp committed
250 251
	data_json, err := json.Marshal(data)
	if err != nil {
wangp's avatar
wangp committed
252
		tx.Rollback()
wangp's avatar
wangp committed
253 254 255
		return nil, err
	}

256 257 258 259 260 261 262 263 264 265 266 267
	if input.SourceCode==9 {
		//收钱吧(扫码枪)

		//调拉卡拉接口
		go lakala_post(input, url, orderID, data_json)

		//返回值
		response := make(map[string]string)
		response["payment_order_code"] = orderID //随机生成的订单号
		return response, nil
	}

wangp's avatar
wangp committed
268
	//调拉卡拉接口
wangp's avatar
wangp committed
269
	err, response, lakala_rtn := lakala_post(input, url, orderID, data_json)
wangp's avatar
wangp committed
270
	if err != nil {
wangp's avatar
wangp committed
271
		InsertPayBillDetailResponseBody(tx, billID, lakala_rtn) //todo
wangp's avatar
wangp committed
272
		tx.Rollback()
wangp's avatar
wangp committed
273 274 275
		return nil, err
	}

wangp's avatar
wangp committed
276 277 278
	// 插入下单成功后返回的参数
	err = InsertPayBillDetailResponseBody(tx, billID, lakala_rtn)
	if err != nil {
wangp's avatar
wangp committed
279
		//beego.Error("下单请求成功 --- 但插入成功后的参数失败")
wangp's avatar
wangp committed
280
		tx.Rollback()
wangp's avatar
wangp committed
281 282
		return nil, err
	}
wangp's avatar
wangp committed
283

wangp's avatar
wangp committed
284
	tx.Commit()
wangp's avatar
wangp committed
285 286 287
	return response, nil
}

288
//支付、退款、支付查询 共通调用
wangp's avatar
wangp committed
289
func lakala_post(input *models.PlaceAnOrderParamInput, url, order_id string, data_json []byte) (error, interface{}, interface{}) {
wangp's avatar
wangp committed
290 291 292 293 294 295 296 297

	var source_code, platform_type uint8
	if input==nil {
		source_code = 0     //支付方式
		platform_type = 0   //平台类型
	} else {
		source_code = input.SourceCode     //支付方式
		platform_type = input.PlatformType //平台类型
wangp's avatar
wangp committed
298 299
	}

wangp's avatar
wangp committed
300
	authorization, err := getAuthorization(platform_type, string(data_json))
wangp's avatar
wangp committed
301
	if err != nil {
wangp's avatar
wangp committed
302
		return err, "", nil
wangp's avatar
wangp committed
303 304 305 306 307 308 309 310 311 312 313 314 315
	}

	fmt.Println(url)
	fmt.Println(authorization)

	req := httplib.Post(url)
	//req.Header("Authorization", "LKLAPI-SHA256withRSA appid=\"\", serial_no=\"\", timestamp=\"\", nonce_str=\"\", signature=\"2233\"")
	req.Header("Authorization", authorization)
	req.Header("Accept", "application/json")
	req.Header("Content-Type", "application/json")
	req.Body(data_json)
	body, err := req.Bytes()
	if err != nil {
wangp's avatar
wangp committed
316
		return err, "", nil
wangp's avatar
wangp committed
317 318 319 320
	}

	temp := make(map[string]interface{}, 0)
	if err = json.Unmarshal(body, &temp); err != nil {
wangp's avatar
wangp committed
321
		return err, "", nil
wangp's avatar
wangp committed
322 323 324 325
	}

	fmt.Println("拉卡拉返回值")
	fmt.Println(temp)
wangp's avatar
wangp committed
326
	if temp["code"] != "000000" && temp["code"] != "BBS00000"{
wangp's avatar
wangp committed
327 328
		//this.Data["json"] = utils.CheckError(errors.New("拉卡拉错误"), temp["msg"].(string))  //todo
		//this.ServeJSON()
wangp's avatar
wangp committed
329
		return errors.New(temp["msg"].(string)), "", temp
wangp's avatar
wangp committed
330 331
	}

wangp's avatar
wangp committed
332
	response := make(map[string]string)
wangp's avatar
wangp committed
333
	response["out_trade_no"] = order_id
wangp's avatar
wangp committed
334
	if source_code==4 || source_code==6 || source_code==1 || source_code==5 || source_code==15 || input.SourceCode==16 || input.SourceCode==17 {
wangp's avatar
wangp committed
335
		//聚合收银台(微信H5、支付宝H5、微信扫码、支付宝扫码、快捷支付(银行卡)(包括微信小程序))
wangp's avatar
wangp committed
336
		//聚合收银台(微信小程序-必康自营)、聚合JSAPI(微信小程序-必康自营)
wangp's avatar
wangp committed
337 338 339 340
		temp2, _ := temp["resp_data"].(map[string]interface{})
		if temp2["counter_url"]=="" {
			return errors.New("拉卡拉返回值「counter_url」为空错误"), "", temp
		}
wangp's avatar
wangp committed
341

wangp's avatar
wangp committed
342
		if source_code==4 || source_code==6 || source_code==15 || source_code==17 {
wangp's avatar
wangp committed
343
			//微信H5、支付宝H5、快捷支付(银行卡)(包括微信小程序)
wangp's avatar
wangp committed
344
			//聚合收银台(微信JSAPI-必康自营)
wangp's avatar
wangp committed
345
			response["m_web_url"] = temp2["counter_url"].(string)
wangp's avatar
wangp committed
346
		} else if source_code==1 || source_code==5 {
wangp's avatar
wangp committed
347 348
			//微信扫码、支付宝扫码
			response["qr_code_url"] = temp2["counter_url"].(string)
wangp's avatar
wangp committed
349 350 351
		} else {
			//聚合收银台(微信小程序-必康自营)
			response["counter_url"] = temp2["counter_url"].(string)
wangp's avatar
wangp committed
352 353
		}

wangp's avatar
wangp committed
354
	} else if source_code==2 || source_code==3 {
wangp's avatar
wangp committed
355
		//聚合主扫(微信JSAPI+微信小程序)(必康自营的微信小程序除外)
wangp's avatar
wangp committed
356 357
		temp2, _ := temp["resp_data"].(map[string]interface{})
		temp3, _ := temp2["acc_resp_fields"].(map[string]interface{})
wangp's avatar
wangp committed
358 359 360
		if temp2["acc_resp_fields"]=="" {
			return errors.New("拉卡拉返回值「acc_resp_fields」为空错误"), "", temp
		}
wangp's avatar
wangp committed
361 362 363 364 365 366 367
		response["app_id"] = temp3["app_id"].(string)
		response["nonce_str"] = temp3["nonce_str"].(string)
		response["package"] = temp3["package"].(string)
		response["pay_sign"] = temp3["pay_sign"].(string)
		response["prepay_id"] = temp3["prepay_id"].(string)
		response["sign_type"] = temp3["sign_type"].(string)
		response["timeStamp"] = temp3["time_stamp"].(string)
wangp's avatar
wangp committed
368 369
	} else if source_code==9 {
		//扫码枪
370 371 372 373
		//mBody := map[string]string{
		//	"payment_order_code": orderID,
		//}
		response["payment_order_code"] = order_id
wangp's avatar
wangp committed
374 375
	}

wangp's avatar
wangp committed
376
	return nil, response, temp
wangp's avatar
wangp committed
377 378
}

wangp's avatar
wangp committed
379 380
func getAuthorization(platform_type uint8, body string) (string, error) {

wangp's avatar
wangp committed
381
	var path_private_key, appid, mchSerialNo string //私钥文件地址
wangp's avatar
wangp committed
382 383 384
	//平台类型 1:saas 2:shop 3:shop mobile 4:收银台 6:bk_shop 7:bk_shop_mobile
	if platform_type==2 || platform_type==3 {
		// 谛宝多多自营
wangp's avatar
wangp committed
385 386
		appid = setting.Conf.Lakala.DbcAppid
		mchSerialNo = setting.Conf.Lakala.DbcSerialNo
wangp's avatar
wangp committed
387 388 389
		path_private_key = setting.Conf.Lakala.DbcPathPrivateKey
	} else if platform_type==6 || platform_type==7 {
		// 必康自营
wangp's avatar
wangp committed
390 391
		appid = setting.Conf.Lakala.BkAppid
		mchSerialNo = setting.Conf.Lakala.BkSerialNo
wangp's avatar
wangp committed
392 393
		path_private_key = setting.Conf.Lakala.BkPathPrivateKey
	} else {
wangp's avatar
wangp committed
394
		// 必康医生
wangp's avatar
wangp committed
395 396
		appid = setting.Conf.Lakala.SaasAppid
		mchSerialNo = setting.Conf.Lakala.SaasSerialNo
wangp's avatar
wangp committed
397 398
		path_private_key = setting.Conf.Lakala.SaasPathPrivateKey
	}
wangp's avatar
wangp committed
399 400 401 402 403 404 405

	nonceStr := RandomString(32) // 构造随机数
	timestamp := strconv.FormatInt(time.Now().Unix(), 10)

	message := appid + "\n" + mchSerialNo + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";


wangp's avatar
wangp committed
406 407
	//todo 退款时,证书???
	//return "", errors.New("输入项「平台类型(platform_type)」数据错误")
wangp's avatar
wangp committed
408

wangp's avatar
wangp committed
409 410
	//base64Sig, err := RSASign([]byte(message), "./cert/dev/OP00000003_private_key.pem")
	base64Sig, err := RSASign([]byte(message), path_private_key)
wangp's avatar
wangp committed
411 412 413
	if err != nil {
		return "", err
	}
wangp's avatar
wangp committed
414

wangp's avatar
wangp committed
415 416
	//fmt.Println("签名2:", base64Sig)
	signature := base64Sig
wangp's avatar
wangp committed
417 418 419 420 421 422
	authorization := "LKLAPI-SHA256withRSA " + "appid=\"" + appid + "\"," + "serial_no=\"" + mchSerialNo + "\"," + "timestamp=\"" + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";

	//System.out.println("authorization message :" + authorization);
	return authorization, nil
}

wangp's avatar
wangp committed
423 424 425 426 427 428 429 430 431
//生产随机字符串
func RandomString(n int) string {
	var letters = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
	result := make([]byte, n)
	rand2.Seed(time.Now().Unix())
	for i := range result {
		result[i] = letters[rand2.Intn(len(letters))]
	}
	return string(result)
432 433
}

wangp's avatar
wangp committed
434 435 436 437 438 439 440 441 442
// 私钥签名过程
func RSASign(data []byte, filename string) (string, error) {
	// 1、选择hash算法,对需要签名的数据进行hash运算
	myhash := crypto.SHA256
	hashInstance := myhash.New()
	hashInstance.Write(data)
	hashed := hashInstance.Sum(nil)
	// 2、读取私钥文件,解析出私钥对象
	privateKey, err := ReadParsePrivaterKey(filename)
443
	if err != nil {
wangp's avatar
wangp committed
444
		return "", err
445
	}
wangp's avatar
wangp committed
446 447
	// 3、RSA数字签名(参数是随机数、私钥对象、哈希类型、签名文件的哈希串),生成base64编码的签名字符串
	bytes, err := rsa.SignPKCS1v15(rand.Reader, privateKey, myhash, hashed)
448
	if err != nil {
wangp's avatar
wangp committed
449
		return "", err
450
	}
wangp's avatar
wangp committed
451
	return base64.StdEncoding.EncodeToString(bytes), nil
452 453
}

wangp's avatar
wangp committed
454 455 456 457
// 读取私钥文件,解析出私钥对象
func ReadParsePrivaterKey(filename string) (*rsa.PrivateKey, error) {
	// 1、读取私钥文件,获取私钥字节
	privateKeyBytes, err := ioutil.ReadFile(filename)
458
	if err != nil {
wangp's avatar
wangp committed
459
		return nil, err
460
	}
wangp's avatar
wangp committed
461 462 463 464 465 466 467 468
	// 2、对私钥文件进行编码,生成加密块对象
	block, _ := pem.Decode(privateKeyBytes)
	fmt.Println(block.Type)
	if block == nil {
		return nil, errors.New("私钥信息错误!")
	}
	// 3、解析DER编码的私钥,生成私钥对象
	prkI, err := x509.ParsePKCS8PrivateKey(block.Bytes)
469
	if err != nil {
wangp's avatar
wangp committed
470
		return nil, err
471
	}
wangp's avatar
wangp committed
472
	privateKey := prkI.(*rsa.PrivateKey)
wangp's avatar
wangp committed
473

wangp's avatar
wangp committed
474 475
	return privateKey, nil
}
wangp's avatar
wangp committed
476

wangp's avatar
wangp committed
477
// GetNoticeURL is 获取回调地址
wangp's avatar
wangp committed
478 479 480 481 482 483 484 485 486
func GetNoticeURL(source_code uint8) string {
	domainName := setting.Conf.PayUrl.DomainName
	if source_code==2 || source_code==3 || source_code==9 {
		//聚合扫码+聚合被扫
		return domainName + "/api/v1/pay/scan_notice"
	} else {
		//其它支付
		return domainName + "/api/v1/pay/cashier_notice"
	}
wangp's avatar
wangp committed
487 488
}

489
//InsertPayBill is 插入 支付订单表中
wangp's avatar
wangp committed
490
func InsertPayBill(tx *sql.Tx, p *models.PlaceAnOrderParamInput, orderID string) (int64, error) {
491 492 493

	var billID int64

wangp's avatar
wangp committed
494
	insertSQL := `insert system_pay_bill set platform_type = ?, platform_info = ?,
495 496 497
source_code = ?, payment_order_code = ?, paymoney = ?*1000, commodity_describe = ?,
commodity_detail = ?, attach = ?, notify_pay_url = ?, pay_type = ?, is_serve = ?`

wangp's avatar
wangp committed
498
	result, err := tx.Exec(insertSQL, p.PlatformType, p.PlatformInfo, p.SourceCode,
499 500 501 502 503 504 505 506 507 508 509 510 511
		orderID, p.GoodsPrice, p.GoodsDes, p.GoodsDetail, p.AttachInfo, p.NoticeURL, p.PayType, p.IsServe)
	if err != nil {
		return billID, err
	}

	billID, err = result.LastInsertId()
	if err != nil {
		return billID, err
	}
	return billID, nil
}

// InsertPayBillDetailRequestBody is 插入支付订单详情表中的 下单参数字段 request_body
wangp's avatar
wangp committed
512
func InsertPayBillDetailRequestBody(tx *sql.Tx, billID int64, requestBody interface{}) error {
513 514 515 516 517

	body, err := json.Marshal(requestBody)
	if err != nil {
		return err
	}
wangp's avatar
wangp committed
518 519
	insertPayBillDetailSQL := `insert system_pay_bill_detail set pay_bill_id = ?, request_body = ?`
	result, err := tx.Exec(insertPayBillDetailSQL, billID, string(body))
520 521 522 523 524 525 526 527 528 529 530 531
	if err != nil {
		return err
	}

	_, err = result.LastInsertId()
	if err != nil {
		return err
	}
	return nil
}

// InsertPayBillDetailResponseBody is 插入支付订单详情表中的 下单参数字段 response_body
wangp's avatar
wangp committed
532
func InsertPayBillDetailResponseBody(tx *sql.Tx, billID int64, responseBody interface{}) error {
533 534 535 536 537

	body, err := json.Marshal(responseBody)
	if err != nil {
		return err
	}
wangp's avatar
wangp committed
538 539
	insertPayBillDetailSQL := `update system_pay_bill_detail set response_body = ? where pay_bill_id = ?`
	result, err := tx.Exec(insertPayBillDetailSQL, string(body), billID)
540 541 542 543 544 545 546 547 548 549 550
	if err != nil {
		return err
	}

	_, err = result.RowsAffected()
	if err != nil {
		return err
	}
	return nil
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
//支付查询 插入db
func InsertPayBillDetailResponseBodyString(tx *sql.Tx, billID int64, responseBody string) error {

	insertPayBillDetailSQL := `update system_pay_bill_detail set response_body = ? where pay_bill_id = ?`
	result, err := tx.Exec(insertPayBillDetailSQL, responseBody, billID)
	if err != nil {
		return err
	}

	_, err = result.RowsAffected()
	if err != nil {
		return err
	}
	return nil
}
wangp's avatar
wangp committed
566 567 568 569 570 571 572 573 574

func GetUID() string {
	u4 := uID.NewV4()
	//if err != nil {
	//	return ""
	//}

	id := fmt.Sprintf("%s", u4)
	return strings.Replace(id, "-", "", -1)
wangp's avatar
wangp committed
575 576
}

wangp's avatar
wangp committed
577 578 579 580
// 拉卡拉退款
func UnifiedRefund(input *models.RefundParamInput, ip string) (interface{}, error) {
	fmt.Println("谛宝多多输入参数(退款)")
	fmt.Println(input)
wangp's avatar
wangp committed
581

wangp's avatar
wangp committed
582
	refundID := GetUID()
wangp's avatar
wangp committed
583

wangp's avatar
wangp committed
584 585 586 587 588
	// 插入数据库
	db, err := mysql.NewPayConn()
	if err != nil {
		return 0, err
	}
wangp's avatar
wangp committed
589

wangp's avatar
wangp committed
590 591 592 593
	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}
wangp's avatar
wangp committed
594

wangp's avatar
wangp committed
595
	defer mysql.CloseTx(tx, err)
wangp's avatar
wangp committed
596

wangp's avatar
wangp committed
597
	//退款订单存在check
wangp's avatar
wangp committed
598
	log_no, trans_term_no, source_code, platform_type, order_create_time, payer_account_no, err := selectRefundBill(tx, input)
wangp's avatar
wangp committed
599 600 601
	if err != nil {
		return nil, err
	}
wangp's avatar
wangp committed
602

wangp's avatar
wangp committed
603 604 605 606
	billID, err := InsertRefundBill(tx, input, refundID)
	if err != nil {
		return nil, err
	}
wangp's avatar
wangp committed
607

wangp's avatar
wangp committed
608 609 610 611
	//数据重组 - start
	now := time.Now()
	now.Add(time.Minute * 60)
	date_time1 := now.Format("20060102150405")
wangp's avatar
wangp committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646

	var version, out_org_code, merchant_no1, merchant_no2, merchant_no3, term_no3, merchant_no4, term_no4 string

	//平台类型 1:saas 2:shop 3:shop mobile 4:收银台 6:bk_shop 7:bk_shop_mobile
	if platform_type==2 || platform_type==3 {
		// 谛宝多多自营
		version = setting.Conf.Lakala.DbcVersion
		out_org_code = setting.Conf.Lakala.DbcAppid
		merchant_no1 = setting.Conf.Lakala.DbcMerchantNo1
		merchant_no2 = setting.Conf.Lakala.DbcMerchantNo2
		merchant_no3 = setting.Conf.Lakala.DbcMerchantNo3
		term_no3 = setting.Conf.Lakala.DbcTermNo3
		merchant_no4 = setting.Conf.Lakala.DbcMerchantNo4
		term_no4 = setting.Conf.Lakala.DbcTermNo4
	} else if platform_type==6 || platform_type==7 {
		// 必康自营
		version = setting.Conf.Lakala.BkVersion
		out_org_code = setting.Conf.Lakala.BkAppid
		merchant_no1 = setting.Conf.Lakala.BkMerchantNo1
		merchant_no2 = setting.Conf.Lakala.BkMerchantNo2
		merchant_no3 = setting.Conf.Lakala.BkMerchantNo3
		term_no3 = setting.Conf.Lakala.BkTermNo3
		merchant_no4 = setting.Conf.Lakala.BkMerchantNo4
		term_no4 = setting.Conf.Lakala.BkTermNo4
	} else {
		// 必康医生
		version = setting.Conf.Lakala.SaasVersion
		out_org_code = setting.Conf.Lakala.SaasAppid
		merchant_no1 = setting.Conf.Lakala.SaasMerchantNo1
		merchant_no2 = setting.Conf.Lakala.SaasMerchantNo2
		merchant_no3 = setting.Conf.Lakala.SaasMerchantNo3
		term_no3 = setting.Conf.Lakala.SaasTermNo3
		merchant_no4 = setting.Conf.Lakala.SaasMerchantNo4
		term_no4 = setting.Conf.Lakala.SaasTermNo4
	}
wangp's avatar
wangp committed
647 648 649

	var url string
	data := make(map[string]interface{})
wangp's avatar
wangp committed
650

wangp's avatar
wangp committed
651 652 653 654 655 656 657
	if source_code==15 {
		//快捷支付(银行卡)
		url = setting.Conf.Lakala.UrlTradeRefund //统一退货接口
	} else {
		//其它
		url = setting.Conf.Lakala.UrlRefund //聚合扫码(退款交易)
	}
wangp's avatar
wangp committed
658

wangp's avatar
wangp committed
659
	data["req_time"] = date_time1
wangp's avatar
wangp committed
660 661
	data["version"] = version
	data["out_org_code"] = out_org_code
wangp's avatar
wangp committed
662 663

	data2 := make(map[string]interface{})
wangp's avatar
wangp committed
664

wangp's avatar
wangp committed
665 666
	//source_code 1: 微信 Native 2:微信小程序 3:微信内支付 4:h5 跳微信
	//5:支付宝(web)-扫码或登录支付宝账户 6:alipay(mobile) 7:alipay(app)
wangp's avatar
wangp committed
667 668 669 670 671
	//9: B2C 10:bk支付宝web 11:bk 支付宝手机 15:快捷支付(银行卡)
	//16:微信小程序-必康自营 17:微信JASPI-必康自营
	if source_code==4 || source_code==6 || source_code==1 ||
		source_code==5 || source_code==15 ||
		source_code==16 || source_code==17 {
wangp's avatar
wangp committed
672
		//聚合收银台(微信H5、支付宝H5、微信扫码、支付宝扫码)
wangp's avatar
wangp committed
673 674
		//聚合收银台(快捷支付(银行卡))
		//聚合收银台(微信小程序-必康自营)
wangp's avatar
wangp committed
675 676
		//data2["merchant_no"] = "8221210701101SB"
		//data2["merchant_no"] = "8222900581201QB"
wangp's avatar
wangp committed
677 678
		if source_code==4 || source_code==6 {
			data2["merchant_no"] = merchant_no1 //微信H5、支付宝H5
wangp's avatar
wangp committed
679
		} else {
wangp's avatar
wangp committed
680
			data2["merchant_no"] = merchant_no2 //其它
wangp's avatar
wangp committed
681 682 683
		}
		//收银台支付时,没有传「term_no」,所以需要取得支付返回值的「trans_term_no」
		data2["term_no"] = trans_term_no
wangp's avatar
wangp committed
684

wangp's avatar
wangp committed
685 686 687 688 689 690 691
	} else if source_code==2 || source_code==3 {
		//聚合主扫(微信JSAPI、微信小程序)
		//data2["merchant_no"] = "8222900701107M5"
		//data2["term_no"] = "A1062976"
		//data2["merchant_no"] = "8221210701101SB"
		data2["merchant_no"] = merchant_no3
		data2["term_no"] = term_no3
wangp's avatar
wangp committed
692

wangp's avatar
wangp committed
693 694 695 696
	} else if source_code==9 {
		//扫码枪
		data2["merchant_no"] = merchant_no4
		data2["term_no"] = term_no4
wangp's avatar
wangp committed
697

wangp's avatar
wangp committed
698
	} else {
wangp's avatar
wangp committed
699
		return nil, errors.New("「source_code」错误,有效值为[1-6,9,15-17]")
wangp's avatar
wangp committed
700
	}
wangp's avatar
wangp committed
701 702 703

	data2["out_trade_no"] = refundID //随机生成的订单号 //商户交易流水号
	//data2["out_trade_no"] = RandomString(32)
wangp's avatar
wangp committed
704
	//扫码支付授权码,设备读取用户APP中的条码或者二维码信息,用户付款码条形码规则见说明
wangp's avatar
wangp committed
705 706
	//data2["auth_code"] = "135178236713755038"
	//data2["auth_code"] = input.DynamicID
wangp's avatar
wangp committed
707 708
	data2["refund_amount"] = input.RefundAmount*100 //退款金额
	data2["refund_reason"] = input.RefundReason //退款原因
wangp's avatar
wangp committed
709

wangp's avatar
wangp committed
710 711
	//input.OrderId = "2023070566210308960791"
	//data2["origin_out_trade_no"] = input.OrderId //原商户交易流水号
wangp's avatar
wangp committed
712
	//data2["origin_trade_no"] = input.OrderId //原拉卡拉交易流水号
wangp's avatar
wangp committed
713
	//data2["origin_log_no"] = input.OrderId //原对账单流水号
wangp's avatar
wangp committed
714 715 716 717 718

	if source_code==15 {
		//快捷支付(银行卡)
		data2["origin_biz_type"] = "4" //原交易类型:1 银行卡,2 外卡,3 扫码,4 线上
		data2["refund_type"] = "00" //当商户进件时退货模式配置的为 指定模式退货时,该字段有效。00:退货帐户,05:商户余额退货,06:终端余额退货
wangp's avatar
wangp committed
719 720
		//data2["origin_card_no"] = "621700*********0114"  todo
		data2["origin_card_no"] = payer_account_no //原交易银行卡号,银行卡退款必填
wangp's avatar
wangp committed
721
		//data2["origin_trade_no"] =   //原交易拉卡拉交易订单号
722
		data2["origin_trade_date"] = order_create_time //原交易日期:yyyyMMdd
wangp's avatar
wangp committed
723 724
	}

wangp's avatar
wangp committed
725
	data2["origin_log_no"] = log_no //原对账单流水号
wangp's avatar
wangp committed
726

wangp's avatar
wangp committed
727

wangp's avatar
wangp committed
728
	data3 := make(map[string]interface{})
wangp's avatar
wangp committed
729 730 731
	//data3["request_ip"] = "10.176.1.192"
	data3["request_ip"] = ip
	//data3["location"] = "+37.123456789,-121.123456789"
wangp's avatar
wangp committed
732 733 734
	data2["location_info"] = make(map[string]interface{})
	data2["location_info"] = data3

wangp's avatar
wangp committed
735 736
	data["req_data"] = make(map[string]interface{})
	data["req_data"] = data2
wangp's avatar
wangp committed
737

wangp's avatar
wangp committed
738
	//return nil, errors.New("输入参数「source_code」错误,有效值为[1-6,9,15-17]")
wangp's avatar
wangp committed
739 740

	//数据重组 - end
wangp's avatar
wangp committed
741 742 743 744
	fmt.Println("拉卡拉输入参数(退款)")
	fmt.Println(data)
	fmt.Println("拉卡拉接口url(退款)")
	fmt.Println(url)
wangp's avatar
wangp committed
745

wangp's avatar
wangp committed
746 747 748 749 750
	// 插入退款请求参数
	err = InsertPayBillDetailRequestBody(tx, billID, data)
	if err != nil {
		return nil, err
	}
wangp's avatar
wangp committed
751 752 753 754 755 756 757 758

	data_json, err := json.Marshal(data)
	if err != nil {
		//this.Data["json"] = utils.CheckError(errors.New("Map转化为byte数组失败"),"异常")
		//this.ServeJSON()
		return nil, err
	}

wangp's avatar
wangp committed
759
	var input2 models.PlaceAnOrderParamInput
760
	input2.SourceCode = source_code
wangp's avatar
wangp committed
761 762
	input2.PlatformType = platform_type

wangp's avatar
wangp committed
763
	//调拉卡拉接口
wangp's avatar
wangp committed
764
	err, _, lakala_rtn := lakala_post(&input2, url, "", data_json)
wangp's avatar
wangp committed
765
	if err != nil {
wangp's avatar
wangp committed
766
		InsertPayBillDetailResponseBody(tx, billID, lakala_rtn)
wangp's avatar
wangp committed
767 768 769
		return nil, err
	}

wangp's avatar
wangp committed
770 771 772 773 774 775 776 777 778 779 780 781
	// 插入退款成功后返回的参数
	err = InsertPayBillDetailResponseBody(tx, billID, lakala_rtn)
	if err != nil {
		//beego.Error("退款请求成功 --- 但退款成功后的参数失败")
		return nil, err
	}

	response := make(map[string]string)
	response["payment_order_code"] = refundID
	return response, nil
}

wangp's avatar
wangp committed
782
//退款订单存在check
wangp's avatar
wangp committed
783
func selectRefundBill(tx *sql.Tx, input *models.RefundParamInput) (string, string, uint8, uint8, string, string, error) {
wangp's avatar
wangp committed
784 785

	var billID int64
786
	var createtime string
wangp's avatar
wangp committed
787
	var status uint
wangp's avatar
wangp committed
788
	var platform_type uint8
wangp's avatar
wangp committed
789
	var source_code uint8
wangp's avatar
wangp committed
790
	var notice_request interface{}
wangp's avatar
wangp committed
791
	var notice_response interface{}
wangp's avatar
wangp committed
792
	var notice_request2 []byte
wangp's avatar
wangp committed
793
	//notice_request2 = []byte(`abc`)
wangp's avatar
wangp committed
794
	//payment_order_code, paymoney
795
	selectRefundBillSQL := `select b.id, DATE_FORMAT(b.createtime, '%Y%m%d') createtime,
wangp's avatar
wangp committed
796
    	b.result_code, b.source_code, b.platform_type, bd.notice_request_body, bd.response_body 
wangp's avatar
wangp committed
797 798 799
		from system_pay_bill b
		left join system_pay_bill_detail bd on b.id=bd.pay_bill_id
		where b._type=0 and b.payment_order_code=?`
wangp's avatar
wangp committed
800
	err := tx.QueryRow(selectRefundBillSQL, input.RefundNo).Scan(&billID, &createtime, &status, &source_code, &platform_type, &notice_request2, &notice_response)
wangp's avatar
wangp committed
801
	if err != nil {
wangp's avatar
wangp committed
802
		return "", "", 0, 0, "", "", err
wangp's avatar
wangp committed
803
	}
wangp's avatar
wangp committed
804

wangp's avatar
wangp committed
805 806
	if source_code==2 || source_code==3 {
		//聚合扫码
wangp's avatar
wangp committed
807
		notice_request = new(models.ScanNoticeInput)
wangp's avatar
wangp committed
808 809 810 811 812 813
		if err := json.Unmarshal(notice_request2, &notice_request); err != nil {
			return "", "", 0, 0, "", "", err
		}
	} else if source_code==9 {
		//聚合被扫
		notice_request = notice_response
wangp's avatar
wangp committed
814
	} else {
wangp's avatar
wangp committed
815
		//聚合收银台
wangp's avatar
wangp committed
816
		notice_request = new(models.CashierNoticeInput)
wangp's avatar
wangp committed
817 818 819
		if err := json.Unmarshal(notice_request2, &notice_request); err != nil {
			return "", "", 0, 0, "", "", err
		}
wangp's avatar
wangp committed
820 821 822
	}

	//fmt.Println(notice_request2)
wangp's avatar
wangp committed
823
	fmt.Println(notice_request)
wangp's avatar
wangp committed
824 825
	fmt.Println("退款订单存在check返回值:")
	fmt.Println(billID)
826
	fmt.Println(createtime)
wangp's avatar
wangp committed
827 828 829 830
	fmt.Println(status)
	fmt.Println(source_code)
	fmt.Println(platform_type)
	//fmt.Println(notice_request2)
wangp's avatar
wangp committed
831 832 833

	// 订单不存在
	if billID <= 0 {
wangp's avatar
wangp committed
834
		return "", "", 0, 0, "", "", errors.New("订单不存在2")
wangp's avatar
wangp committed
835 836 837 838
	}

	// 订单未结算
	if status != 1 {
wangp's avatar
wangp committed
839
		return "", "", 0, 0, "", "", errors.New("订单未结算")
wangp's avatar
wangp committed
840 841
	}

wangp's avatar
wangp committed
842
	if source_code==0 {
wangp's avatar
wangp committed
843
		return "", "", 0, 0, "", "", errors.New("「source_code」错误,有效值为[1-6,9,15-17]")
wangp's avatar
wangp committed
844 845
	}

wangp's avatar
wangp committed
846 847
	// 获取「对账单流水号」、「交易终端号」和「付款人账号」,退款用
	var log_no, trans_term_no, payer_account_no string
wangp's avatar
wangp committed
848 849
	if source_code==2 || source_code==3 {
		//聚合扫码
850
		log_no = notice_request.(*models.ScanNoticeInput).LogNo
wangp's avatar
wangp committed
851
		if log_no=="" {
wangp's avatar
wangp committed
852
			return "", "", 0, 0, "", "", errors.New("「对账单流水号」未取得错误")
wangp's avatar
wangp committed
853
		}
wangp's avatar
wangp committed
854 855 856 857 858 859 860 861 862 863 864 865 866
	} else if source_code==9 {
		//聚合被扫
		//resp_data := notice_request.(map[string]interface{})["resp_data"]
		//fmt.Println("resp_data返回值:", resp_data)
		//if resp_data == nil {
		//	return "", "", 0, 0, "", "", errors.New("数据错误:resp_data返回值为空")
		//}
		//log_no = resp_data.(map[string]interface{})["log_no"].(string) //拉卡拉对账单流水号
		log_no = "66210310187398"
		//fmt.Println("log_no返回值:", log_no)
		if log_no == "" {
			return "", "", 0, 0, "", "", errors.New("数据错误:拉卡拉对账单流水号为空")
		}
wangp's avatar
wangp committed
867 868 869
	} else {
		//其它支付
		// 针对有的支付,不需要传「交易终端号」时,需要用支付返回的「交易终端号」进行退款
870
		log_no = notice_request.(*models.CashierNoticeInput).OrderTradeInfo.(map[string]interface{})["log_no"].(string)
wangp's avatar
wangp committed
871
		if log_no=="" {
wangp's avatar
wangp committed
872
			return "", "", 0, 0, "", "", errors.New("「对账单流水号」未取得错误")
wangp's avatar
wangp committed
873
		}
874
		trans_term_no = notice_request.(*models.CashierNoticeInput).TransTermNo
wangp's avatar
wangp committed
875
		if trans_term_no=="" {
wangp's avatar
wangp committed
876
			return "", "", 0, 0, "", "", errors.New("「交易终端号」未取得错误")
wangp's avatar
wangp committed
877
		}
wangp's avatar
wangp committed
878 879
		// 银行卡支付时,获取付款人账号
		payer_account_no = notice_request.(*models.CashierNoticeInput).OrderTradeInfo.(map[string]interface{})["payer_account_no"].(string)
wangp's avatar
wangp committed
880 881
	}

wangp's avatar
wangp committed
882
	return log_no, trans_term_no, source_code, platform_type, createtime, payer_account_no, nil
wangp's avatar
wangp committed
883 884
}

wangp's avatar
wangp committed
885 886
//InsertRefundBill is 插入 支付订单表中
func InsertRefundBill(tx *sql.Tx, p *models.RefundParamInput, refundID string) (int64, error) {
wangp's avatar
wangp committed
887

wangp's avatar
wangp committed
888 889 890 891
	var billID int64
	//todo 原source
	//insertSQL := `insert system_pay_bill set platform_type = ?, source_code = ?,
	//payment_order_code = ?, paymoney = ?*1000, pay_type = 4, attach = ?, _type = 1, original_payment_order_code = ?`
wangp's avatar
wangp committed
892

wangp's avatar
wangp committed
893 894 895 896 897 898 899 900
	//platformType, sourceCode, checkSn, refundAmount, attach, orderID
	//result, err := tx.Exec(insertSQL, p.PlatformType, p.PlatformInfo, p.SourceCode,
	//	orderID, p.GoodsPrice, p.GoodsDes, p.GoodsDetail, p.AttachInfo, p.NoticeURL, p.PayType, p.IsServe)

	insertSQL := `insert system_pay_bill set original_payment_order_code=?, payment_order_code=?, paymoney=?*1000, _type=1`

	//差 platformType, sourceCode, attach 和 pay_type = 4
	result, err := tx.Exec(insertSQL, p.RefundNo, refundID, p.RefundAmount)
wangp's avatar
wangp committed
901
	if err != nil {
wangp's avatar
wangp committed
902
		return billID, err
wangp's avatar
wangp committed
903
	}
wangp's avatar
wangp committed
904 905

	billID, err = result.LastInsertId()
wangp's avatar
wangp committed
906
	if err != nil {
wangp's avatar
wangp committed
907
		return billID, err
wangp's avatar
wangp committed
908 909
	}

wangp's avatar
wangp committed
910 911
	return billID, nil
}
912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938

// 拉卡拉支付查询
func OrderState(input *models.OrderStateInput) (interface{}, error) {
	fmt.Println("谛宝多多输入参数(支付查询)")
	fmt.Println(input)

	//refundID := GetUID()

	order_id := input.OrderId
	if order_id == "" {
		return nil, errors.New("账单不存在")
	}

	// 插入数据库
	db, err := mysql.NewPayConn()
	if err != nil {
		return 0, err
	}

	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}

	defer mysql.CloseTx(tx, err)

	var isExist uint
wangp's avatar
wangp committed
939
	err = tx.QueryRow(`select count(id) from system_pay_bill where payment_order_code = ?`, order_id).Scan(&isExist)
940 941 942 943 944 945 946 947
	if err != nil {
		return nil, err
	}

	if isExist == 0 {
		return nil, fmt.Errorf("账单不存在")
	}

wangp's avatar
wangp committed
948
	//todo 删除不需要的变量
wangp's avatar
wangp committed
949
	querySQL := `select id, source_code, result_code, payment_order_code, attach, _type, platform_type from system_pay_bill where payment_order_code = ?`
950

wangp's avatar
wangp committed
951 952
	result := new(models.OrderState)
	//var result_code uint8
wangp's avatar
wangp committed
953
	var sourceCode, platformType uint
954 955 956 957 958 959
	var paymentOrderCode string
	var attach string
	var billID int64
	var billType uint8

	err = db.QueryRow(querySQL, order_id).Scan(&billID, &sourceCode,
wangp's avatar
wangp committed
960
		&result.State, &paymentOrderCode, &attach, &billType, &platformType)
961 962 963 964 965
	if err != nil {
		return nil, err
	}

	// 如果是 未结算成功、并且是收钱吧渠道的账单
wangp's avatar
wangp committed
966
	if result.State == 0 && sourceCode == 9 { //todo wangpei
967
		// 查询收钱吧支付是否成功
wangp's avatar
wangp committed
968
		state, err := SqbQueryOrderState(tx, paymentOrderCode, attach, billID, billType, platformType, sourceCode)
969 970 971 972
		if err != nil {
			return nil, err
		}

wangp's avatar
wangp committed
973
		result.State = state
974 975
	}

wangp's avatar
wangp committed
976
	return result, nil
977 978 979
}

//订单状态 0: 未结算 1: 结算成功 2: 结算失败
wangp's avatar
wangp committed
980
func SqbQueryOrderState(tx *sql.Tx, paymentOrderCode, attach string, billID int64, billType uint8, platformType, sourceCode uint) (uint8, error) {
981 982 983 984 985 986 987 988

	fmt.Println("attachMap: ", attach)
	var attachMap map[string]interface{}
	err := json.Unmarshal([]byte(attach), &attachMap)
	if err != nil {
		return 0, err
	}

wangp's avatar
wangp committed
989 990 991 992
	//storeSn := attachMap["store_sn"].(string)
	//if storeSn == "" {
	//	return 0, fmt.Errorf("参数错误")
	//}
993 994 995 996 997 998 999 1000

	var input2 models.PlaceAnOrderParamInput
	//input2.SourceCode = source_code
	//input2.PlatformType = platform_type

	//url := "https://test.wsmsd.cn/sit/api/v3/labs/query/tradequery" //测试
	//url := "https://s2.lakala.com/api/v3/labs/query/tradequery" //正式

wangp's avatar
wangp committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
	url := setting.Conf.Lakala.UrlOrderState //聚合扫码-交易查询

	//数据重组 - start
	var merchant_no3, term_no3, merchant_no4, term_no4 string
	var merchant_no, term_no, version, out_org_code string
	now := time.Now()
	now.Add(time.Minute * 60)
	date_time1 := now.Format("20060102150405")
	//平台类型 1:saas 2:shop 3:shop mobile 4:收银台 6:bk_shop 7:bk_shop_mobile
	if platformType==2 || platformType==3 {
		// 谛宝多多自营
		version = setting.Conf.Lakala.DbcVersion
		out_org_code = setting.Conf.Lakala.DbcAppid
		//merchant_no1 = setting.Conf.Lakala.DbcMerchantNo1
		//merchant_no2 = setting.Conf.Lakala.DbcMerchantNo2
		merchant_no3 = setting.Conf.Lakala.DbcMerchantNo3
		term_no3 = setting.Conf.Lakala.DbcTermNo3
		merchant_no4 = setting.Conf.Lakala.DbcMerchantNo4
		term_no4 = setting.Conf.Lakala.DbcTermNo4
	} else if platformType==6 || platformType==7 {
		// 必康自营
		version = setting.Conf.Lakala.BkVersion
		out_org_code = setting.Conf.Lakala.BkAppid
		//merchant_no1 = setting.Conf.Lakala.BkMerchantNo1
		//merchant_no2 = setting.Conf.Lakala.BkMerchantNo2
		merchant_no3 = setting.Conf.Lakala.BkMerchantNo3
		term_no3 = setting.Conf.Lakala.BkTermNo3
		merchant_no4 = setting.Conf.Lakala.BkMerchantNo4
		term_no4 = setting.Conf.Lakala.BkTermNo4
	} else {
		// 必康医生
		version = setting.Conf.Lakala.SaasVersion
		out_org_code = setting.Conf.Lakala.SaasAppid
		//merchant_no1 = setting.Conf.Lakala.SaasMerchantNo1
		//merchant_no2 = setting.Conf.Lakala.SaasMerchantNo2
		merchant_no3 = setting.Conf.Lakala.SaasMerchantNo3
		term_no3 = setting.Conf.Lakala.SaasTermNo3
		merchant_no4 = setting.Conf.Lakala.SaasMerchantNo4
		term_no4 = setting.Conf.Lakala.SaasTermNo4
	}
1041

wangp's avatar
wangp committed
1042 1043 1044 1045 1046 1047 1048 1049 1050
	if sourceCode==2 || sourceCode==3 {
		//聚合主扫(微信JSAPI、微信小程序)
		merchant_no = merchant_no3
		term_no = term_no3
	} else if sourceCode==9 {
		//聚合被扫(扫码枪)
		merchant_no = merchant_no4
		term_no = term_no4
	}
wangp's avatar
wangp committed
1051

1052
	data := make(map[string]interface{})
wangp's avatar
wangp committed
1053 1054 1055 1056 1057 1058 1059 1060
	data["req_time"] = date_time1
	data["version"] = version
	data["out_org_code"] = out_org_code

	data2 := make(map[string]interface{})
	data2["merchant_no"] = merchant_no //商户号
	data2["term_no"] = term_no//终端号
	data2["out_trade_no"] = paymentOrderCode //商户交易流水号
1061
	//data["trade_no"] = trade_no //拉卡拉交易流水号
wangp's avatar
wangp committed
1062
	data["req_data"] = data2
1063 1064 1065 1066 1067
	data_json, err := json.Marshal(data)
	if err != nil {
		return 0, err
	}

wangp's avatar
wangp committed
1068 1069
	fmt.Println("拉卡拉请求参数(支付查询)", data_json)

1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
	//调拉卡拉接口
	err, _, lakala_rtn := lakala_post(&input2, url, "", data_json)
	if err != nil {
		InsertPayBillDetailResponseBody(tx, billID, lakala_rtn)
		return 0, err
	}

	// 插入成功后返回的结果
	err = InsertPayBillDetailResponseBody(tx, billID, lakala_rtn)
	if err != nil {
		//beego.Error("支付查询请求成功 --- 但退成功后的插入参数失败")
		return 0, err
	}

	//INIT-初始化 CREATE-下单成功 SUCCESS-交易成功 FAIL-交易失败 DEAL-交易处理中
	//UNKNOWN-未知状态 CLOSE-订单关闭 PART_REFUND-部分退款 REFUND-全部退款(或订单被撤销)
wangp's avatar
wangp committed
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
	code := lakala_rtn.(map[string]interface{})["code"] //交易code
	fmt.Println("code返回值:", code)
	if code != "BBS00000" {
		// 返回失败
		return 0, nil //todo 返回 2: 结算失败 ?
	}
	resp_data := lakala_rtn.(map[string]interface{})["resp_data"]
	fmt.Println("resp_data返回值:", resp_data)
	if resp_data == nil {
		// 返回失败
		return 0, nil //todo 返回 2: 结算失败 ?
	}
	trade_state := resp_data.(map[string]interface{})["trade_state"] //交易状态
	fmt.Println("trade_state返回值:", trade_state)
1100 1101 1102 1103 1104
	if trade_state != "SUCCESS" {
		// 返回未结算
		return 0, nil //todo 返回 2: 结算失败 ?
	}

wangp's avatar
wangp committed
1105
	querySQL := `select result_code from system_pay_bill where id = ?`
1106 1107 1108 1109 1110 1111

	var resultCode uint
	err = tx.QueryRow(querySQL, billID).Scan(&resultCode)
	if err != nil {
		return 0, errors.New("查询失败:" + err.Error())
	}
wangp's avatar
wangp committed
1112
	fmt.Println("resultCode返回值:", resultCode)
1113 1114 1115
	// 如果支付过、则直接返回
	if resultCode != 0 && resultCode != 2 {
		// 返回支付成功
wangp's avatar
wangp committed
1116
		fmt.Println("支付过、则直接返回支付成功")
1117 1118 1119 1120 1121 1122 1123
		return 1, nil
	}

	// 如果支付成功则改变状态
	err = BillPayStateSuccess(tx, billID)
	if err != nil {
		//beego.Error("改变支付状态为成功时错误: ", err)
wangp's avatar
wangp committed
1124 1125
		//tx.Rollback()
		fmt.Println("改变支付状态为成功时错误:", billID)
1126 1127 1128 1129 1130
		return 0, nil
	}

	return 1, nil
}