package main import ( "context" "fmt" common "git.mashibing.com/msb_47094/shopping-comm" "github.com/asim/go-micro/plugins/registry/consul/v4" "github.com/gin-gonic/gin" "github.com/plutov/paypal/v4" "github.com/smartwalle/alipay/v3" "go-micro.dev/v4" "go-micro.dev/v4/registry" "io/ioutil" "log" "net/http" "os" "os/exec" "payment/proto" "strings" ) // 将公钥提供给支付宝(通过支付宝后台上传)对我们请求的数据进行签名验证,我们的代码中将使用私钥对请求数据签名。 // 目前新创建的支付宝应用只支持证书方式认证,已经弃用之前的公钥和私钥的方式 // 私钥:用于加密请求参数; // 公钥:用于解密通过 私钥加密后的 请求参数。 var ( // appId APPID = "2021000116681444" // 应用公钥 AliAppPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1o6GRM72PKbU299+VmOd1527hKp+//fpEPkz7yBHBCoaAAASuIaaQyuHHtJAcjVlb4XNjLoRyIXQ71rPQaucs/5qjmvyPAlfBNJhVaUAV5ZX7WtXHMAEdTBzVODP5axjY5BSzSmpvm9fNPDuaU3ayyqENP5yoHFs2zTSpnwRoh9Ct+urqfrAJRBx435OwVJ6Abv6blKcXMSRLlgq9hM5fbzFHv7OQ8QXvrsB9NA6s2PELI5hbLFuW0T8WyX4AaFIo2SHnHGludrDwKCxO3HolwjZoQKNcsZhDOG0A3kcVUowpnP3SqkbsfVId943KxvXTIouAoYYbfD6/BKcVlC/QIDAQAB" //支付宝公钥 AliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhA9A6B+gV6pzSv9KKUFcqMZKrFIYOamHIeviQy6KgFuWekGG7KA6agJyGaYrogTpp97NyopgORAK+D5J7bRdcJ1smkpHlyXF0P8D9H/+wZn++1TSQYWWoPJbQXX+l0Ma42O6ISckwXHeZr0tLWUaAoTnTkSAqR0e5LtAFusND6EY/pFFJONxM2Fouwb9WiNCw6J1zQDpO1Y0bxVgQy9v19N/Qw04MtPakua2BqyZctbLggA8WhusCzbTMRZCcOXdYFajPqSvVz5278K6RGKjVeDVBUuaUcA394v1I9tHIa41o8P7j0DhFfDS5Lo8npjhkxcF2wHqfzf5NH041jwAQQIDAQAB" //私钥 PrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnWjoZEzvY8ptTb335WY53XnbuEqn7/9+kQ+TPvIEcEKhoAABK4hppDK4ce0kByNWVvhc2MuhHIhdDvWs9Bq5yz/mqOa/I8CV8E0mFVpQBXllfta1ccwAR1MHNU4M/lrGNjkFLNKam+b1808O5pTdrLKoQ0/nKgcWzbNNKmfBGiH0K366up+sAlEHHjfk7BUnoBu/puUpxcxJEuWCr2Ezl9vMUe/s5DxBe+uwH00DqzY8QsjmFssW5bRPxbJfgBoUijZIeccaW52sPAoLE7ceiXCNmhAo1yxmEM4bQDeRxVSjCmc/dKqRux9Uh33jcrG9dMii4Chhht8Pr8EpxWUL9AgMBAAECggEAYsQ3QZE+Yt1bmjRUrpKSKBTSL9NICveJ75I6OffQYtXZ7fcCNS+X0qOvJhQElE8I7qUPYedNep2+CTaDUbLdxdjEShhdjENefAmN/GmKU/xw1rGMLOGaCuv7rMg6z46KHzbzhgT+zdDaag84lhnRySjE/cV8yG0qVqhFUuPjEFyMrY8lb/68P+E3P4Vm+hvdaOe10ayLmYm7YBh4Z7eSdhSxENBs+7dIG37Z2xC6FQRPm5qLrFdP03tianX71ZU/J7yky4HceqW4lIW8g4CSbWlCKewaucvnZ7q449/P/PSIbPr4KxQS8bGooQF6LGYEkRISWpYIQWBSjXvUU7PDaQKBgQDV3Hgwp93FdLU414ArdXzbklzVC3SEKdIXEBmt9s+Ec13I1xPDjM1HFezow4S/aaqi5soYyR6koVvsaXeHk+cNlphgZj6lz+p0BQvCvTrjkRFwSDdlBNuxgaiwZbjjUHZPwO42d3k2kiUwyRNcGIyDyPzo4b19D06VX2JIKdpp+wKBgQDIU8ZfQUj11Zgqx/dqd5XASGtoSQNwZPROJyLFwTMg6okgdevdoWaFgRUttPDRBhdcrtmVq7voJ35xoriKNFCSvkZc8GAVKiYgIGLXNscDKZx1EP5yc9VVbUnnTW4QXBQRB+VcLGmuh1DOPTkP+sEsTZhPM5TTMCX9HxrDtW6tZwKBgQCAlkBaGQTaTbMNC14QQ2Mgbp+MpYeYU8DzhwW5uNXLcMZqFQ/YG1fuLvu0dKLjqHgl3JiVUJAxMqgfvMZW6ZIadHsIM1Hlxt7UhZgtrjOzUq1mkrVj8wjZcPlpnrANVXrdt0ZDz5A9RKBB9hTC4ivSrU2MBPc3M7XvUFu6wheGcwKBgQCCMCeIOiZPVWuZyfDZ6TOSDb53vJOWlJVMwRRRDljK+ID7bodFtqGo+5Wm6aNjRCEko6FWKpBotFnxQb3KW2tNooiZ18Gpn4W9dS6nDLtTK9S5I70o5mxrIyZXQrPXv+9ujgIZ3+cifGAgWBtgbibiQt9MAYqjoPPfRzqem6d82wKBgQCjcqFOK7Ff0bSz6S2PzFLWyHBlrEKXI+9+9N5nS8aFB8uJduu0PqK4CXs6FqbY+6xuZ9Qdhe9j2NXoqZoJyQlb8/aL1etT+/JP0Md9Wi0v9SVnnz6Ci1RmJEjO02Q/xrpphEbK87h7YpNUI4flHR4ZCr9EmXqdXRTuXImUImc3uw==" ApliClient, _ = alipay.New(APPID, PrivateKey, false) FindOrderClient = proto.NewFindOrderService("", nil) UpdateTraderClient = proto.NewUpdateTradeOrderService("", nil) //PayPal国际支付 PayPalClientID = "AX5c8C-Z9P5vXgs22Q3MWKaEKvVa5-vtU3jtNrQe8W2s-x8eXYn_2aA-e4paaHo6I0Z9eba0Ur2LTdZI" PayPalPublicKey = "" PayPalSecretID = "EB_svAAyczD2OoCMh2HMA4ApBysCbHli8gOpFUfKLOaI5zkoePeNd54OI1PT5yDtAqNsWgho7IYNdqFR" //真实环境 paypal.APIBaseLive PaypalClient, _ = paypal.NewClient(PayPalClientID, PayPalSecretID, paypal.APIBaseSandBox) ) // 初始化的init func init() { //PayPal国际支付 //PaypalClient, _ = paypal.NewClient(PayPalClientID, PayPalSecretID, paypal.APIBaseSandBox) PaypalClient.SetLog(os.Stdout) // Set log to terminal stdout accessToken, err := PaypalClient.GetAccessToken(context.Background()) fmt.Println("PayPal国际支付 :\n", accessToken, " \n ", err) //支付宝支付 ApliClient.LoadAppPublicCert(AliAppPublicKey) ApliClient.LoadAliPayPublicCert(AliPublicKey) //证书的方式 ApliClient.LoadAliPayRootCert() //注册中心 consulReg := consul.NewRegistry(func(options *registry.Options) { options.Addrs = []string{common.ConsulReistStr} }) rpcServer := micro.NewService( micro.Name("shop-payment"), micro.Registry(consulReg), ) FindOrderClient = proto.NewFindOrderService("trade-order", rpcServer.Client()) UpdateTraderClient = proto.NewUpdateTradeOrderService("trade-order", rpcServer.Client()) } func TradeWapPayPal(c *gin.Context) { //order, err := PaypalClient.CreateOrder(paypal.OrderIntentCapture, []paypal.PurchaseUnitRequest{paypal.PurchaseUnitRequest{ReferenceID: "ref-id", Amount: paypal.Amount{Total: "7.00", Currency: "USD"}}}) } // 手机端的支付 弹出选择APP 还是 H5 func TradeWapAliPay(c *gin.Context) { fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TradeAppAliPay ") var pay = alipay.TradeWapPay{} pay.TotalAmount = c.Query("payAmount") pay.OutTradeNo = c.Query("orderNo") //支付之后 支付宝回调的API //pay.ReturnURL = "http://127.0.0.1:8086/return" pay.NotifyURL = "http://j8utmw.natappfree.cc/return" pay.Body = "APP订单" pay.Subject = "商品标题" res, err := ApliClient.TradeWapPay(pay) if err != nil { fmt.Println("支付失败 :", err) } payURL := res.String() payURL = strings.Replace(payURL, "&", "^&", -1) exec.Command("cmd", "/c", "start", payURL).Start() } // 网站页面扫码支付 func TradePageAlipay(c *gin.Context) { fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TradePageAlipay ") var p = alipay.TradePagePay{} p.NotifyURL = "http://j8utmw.natappfree.cc/return" //支付异步 //p.ReturnURL = "http://127.0.0.1:8086/return" //同步 p.Subject = "商品支付" p.OutTradeNo = c.Query("orderNo") p.TotalAmount = c.Query("payAmount") p.ProductCode = "FAST_INSTANT_TRADE_PAY[" res, err := ApliClient.TradePagePay(p) if err != nil { fmt.Println("支付失败 :", err) } payURL := res.String() payURL = strings.Replace(payURL, "&", "^&", -1) exec.Command("cmd", "/c", "start", payURL).Start() } // 回调函数 /* gmt_create=2022-11-17+13%3A39%3A42& charset=utf-8& gmt_payment=2022-11-17+13%3A39%3A48& notify_time=2022-11-17+13%3A39%3A49& subject=%E4%BF%AE%E6%AD%A3%E4%BA%86%E4%B8%AD%E6%96%87%E7%9A%84+Bug& sign=Q%2FqJv73maQ45zEdJfYfce9%2FeCDYx03otzJL67wetT1q%2Ft1vrVrpf8EHDpDQxKzcchDqOJ%2B1v3lDyhHwd4KUHd3z9APw%2BGzonHYgccuLNwEwaYQ8Pv7PjzFMOvS2HiHptUdYMWFXKHnYi3AE%2FuBtxGASljBuMms9jnABf1xFM4BVVhdmtSdMtlhbJ0eDNNs0pAs1tdCXdX%2FV6j%2BWi6GSU7VYMRzhzhlWYm%2FTSZao4QNqjkoY6j1G4MWx%2Fvmyk3SgItDSEpECxzO2Vt0F0slbTUJwqllkQ%2Fk323VvXFBHxHOxltpnrZfegYK%2B0mE4jcpQ9jRCnXRCDMHKI9adl6kJX9A%3D%3D& buyer_id=2088622955228317& invoice_amount=10.00& version=1.0& notify_id=2022111700222133949028310528415537& fund_bill_list=%5B%7B%22amount%22%3A%2210.00%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D& notify_type=trade_status_sync& out_trade_no=2022-11-17+13%3A39%3A33.8566275+%2B0800+CST+m%3D%2B3.273247501& total_amount=10.00& trade_status=TRADE_SUCCESS& trade_no=2022111722001428310502276237& auth_app_id=2021000116681444& receipt_amount=10.00& point_amount=0.00& app_id=2021000116681444& buyer_pay_amount=10.00& sign_type=RSA2& seller_id=2088621954959062 */ func AliPayNotify(c *gin.Context) { fmt.Println(" >>>>>>>>>>>>>>>>> AliPayNotify >>>>>>>>>>>>>>>>>") //获取请求报文的长度 //conLen := c.Request.ContentLength ////新建一个字节切片 长度 //body := make([]byte, conLen) //n, _ := c.Request.Body.Read(body) //改进读取的方法 data, _ := ioutil.ReadAll(c.Request.Body) vals := string(data[0:len(data)]) fmt.Println(vals) //验证是否支付成功 if strings.Contains(vals, "TRADE_SUCCESS") { kv := strings.Split(vals, "&") var no string for k, v := range kv { fmt.Println(k, ":", v) //out_trade_no=xxxx if strings.HasPrefix(v, "out_trade_no") { index := strings.Index(v, "=") no = v[index+1 : len(v)] } } fmt.Println("订单:", no, "成功支付") //远程调用 服务 //查询订单详情 req := &proto.FindOrderReq{} //req.Id = req.OrderNo = no obj, err := FindOrderClient.FindOrder(context.TODO(), req) if err != nil { log.Println("findOrder err :", err) //common.RespFail(c.Writer, resp, "查询失败") } fmt.Println("findOrder:", obj) //c.JSON(http.StatusOK, gin.H{"findOrder": "SUCCESS", "Message": obj}) //修改订单 reqUpdate := &proto.AddTradeOrderReq{} tradeOrder := &proto.TradeOrder{} tradeOrder.ID = obj.TradeOrder.ID reqUpdate.TradeOrder = tradeOrder //订单状态(1:待支付,2:已关闭,3:已支付,4:已发货,5:已收货,6:已完成,7:已追评) reqUpdate.TradeOrder.OrderStatus = 3 _, err = UpdateTraderClient.UpdateTradeOrder(context.TODO(), reqUpdate) if err != nil { log.Println("/UpdateTradeOrder err ", err) return } c.JSON(http.StatusOK, gin.H{"reslut": "SUCCESS", "Message": "修改订单支付成功!"}) } } // 生成收款订单 func CreateOrderPayer(c *gin.Context) { purchaseUnits := make([]paypal.PurchaseUnitRequest, 1) purchaseUnits[0] = paypal.PurchaseUnitRequest{ Amount: &paypal.PurchaseUnitAmount{ Currency: "USD", //收款类型 Value: c.Query("amount"), //收款数量 }, InvoiceID: c.Query("orderNo"), ReferenceID: "123", Description: "商品支付", } payer := &paypal.CreateOrderPayer{ Name: &paypal.CreateOrderPayerName{ //GivenName: user_idStr, //Surname: user_idStr, }, } appContext := &paypal.ApplicationContext{ ReturnURL: "http://j8utmw.natappfree.cc/payPalBack?orderNo=" + c.Query("orderNo"), //回调链接 } //CreateOrder(ctx context.Context, intent string, purchaseUnits []PurchaseUnitRequest, payer *CreateOrderPayer, appContext *ApplicationContext) orderResponse, err := PaypalClient.CreateOrder(context.Background(), "CAPTURE", purchaseUnits, payer, appContext) if err != nil { log.Println("create order errors:", err) c.JSON(http.StatusNotExtended, gin.H{"reslut": err, "Message": "构建订单失败!", "CODE": http.StatusNotExtended}) return } //c.Header("ID", orderResponse.ID) payURL := (*orderResponse).Links[1].Href payURL = strings.Replace(payURL, "&", "^&", -1) common.SetUserToken() //https://www.sandbox.paypal.com/checkoutnow?token=85V82337B3775564V exec.Command("cmd", "/c", "start", payURL).Start() //(*order).Links[1].Href就是支付的链接 } // 回调(可以利用上面的回调链接实现) // https://www.sandbox.paypal.com/webapps/hermes? // flow=1-P&ulReturn=true& // token=85V82337B3775564V& // rcache=2& // useraction=CONTINUE& // cookieBannerVariant=1& // targetService4174=xorouternodeweb&country.x=C2& // locale.x=zh_XC func PaypalCallback(c *gin.Context) { //c, err := paypal.NewClient(clientID, secretID, paypal.APIBaseSandBox) //if err != nil { // return err //} //_, err = c.GetAccessToken() //if err != nil { // return err //} //“status”:“COMPLETED 或者 PENDING” 说明支付成功了 ctor := paypal.CaptureOrderRequest{} //CaptureOrder(ctx context.Context, orderID string, captureOrderRequest CaptureOrderRequest) order, err := PaypalClient.CaptureOrder(context.Background(), c.Query("ID"), ctor) o, _ := PaypalClient.GetOrder(context.Background(), c.Query("ID")) log.Println(o, "\n", order) if err != nil { log.Println("/UpdateTradeOrder err ", err) //return } //查看回调完成后订单状态是否支付完成。 if (*order).Status != "COMPLETED" { log.Println("/UpdateTradeOrder err ", err) c.JSON(http.StatusNotExtended, gin.H{"reslut": err, "Message": "订单回调失败!", "CODE": http.StatusNotExtended}) return } c.JSON(http.StatusOK, gin.H{"reslut": "SUCCESS", "Message": "修改订单支付成功!"}) } func main() { r := gin.Default() r.SetTrustedProxies([]string{common.QSIp}) r.GET("/appPay", TradeWapAliPay) r.GET("/pagePay", TradePageAlipay) r.POST("/return", AliPayNotify) //payPal r.GET("/payPal", CreateOrderPayer) r.GET("/payPalBack", PaypalCallback) r.Run(":8086") }