You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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")
}