stripe支付

java

依赖

	<!-- https://mvnrepository.com/artifact/com.stripe/stripe-java -->
    <dependency>
        <groupId>com.stripe</groupId>
        <artifactId>stripe-java</artifactId>
        <version>21.5.0</version>
    </dependency>

创建订单

	@RequestMapping(value = "/create")
    public String create() throws StripeException {
    
    
    
    	//账号私钥
        Stripe.apiKey = "sk_test_。。。";
		//10u订单
        PaymentIntentCreateParams params =
                PaymentIntentCreateParams
                        .builder()
                        .setAmount(1000L)
                        .setCurrency("usd")
                        .setAutomaticPaymentMethods(
                                PaymentIntentCreateParams.AutomaticPaymentMethods.builder().setEnabled(true).build()
                        )
                        .build();

        PaymentIntent paymentIntent = PaymentIntent.create(params);
        System.out.println(JSONObject.toJSONString(paymentIntent));

        JSONObject map = new JSONObject();
        map.put("clientSecret", paymentIntent.getClientSecret());
        System.out.println("订单号:" + paymentIntent.getId());
        return JSONObject.toJSONString(map);
    }

支付结果回调

	@RequestMapping(value = "/webhook")
    public static String webhook(HttpServletRequest request, HttpServletResponse response)  {
    
    
        // This is your Stripe CLI webhook secret for testing your endpoint locally.
        String endpointSecret = "whsec_0。。。";

        try {
    
    
            String payload = getRequestPostStr(request);
            String sigHeader = request.getHeader("Stripe-Signature");

            Event event  = Webhook.constructEvent(
                    payload, sigHeader, endpointSecret
            );
            EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
            StripeObject stripeObject = dataObjectDeserializer.getObject().get();
            // Handle the event
            switch (event.getType()) {
    
    
                case "payment_intent.succeeded": {
    
    
                    //支付成功
                    System.out.println("payment_intent.succeeded");
                    System.out.println("订单号:" + ((PaymentIntent) stripeObject).getId());
                    break;
                }
                case "payment_intent.payment_failed": {
    
    
                    //支付失败
                    System.out.println("payment_intent.payment_failed");
                    System.out.println("订单号:" + ((PaymentIntent) stripeObject).getId());
                    break;
                }
                // ... handle other event types
                default:
                    System.out.println("Unhandled event type: " + event.getType());
            }
        } catch (Exception e) {
    
    
            // Invalid payload
            response.setStatus(400);
            return "";
        }
        response.setStatus(200);
        return "";
    }
    
	public static String getRequestPostStr(HttpServletRequest request)
            throws IOException {
    
    
        byte buffer[] = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
    
    
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }

    /* @param request
     * @return
     * @throws IOException
     */
    public static byte[] getRequestPostBytes(HttpServletRequest request)
            throws IOException {
    
    
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
    
    
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength; ) {
    
    
            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
    
    
                break;
            }
            i += readlen;
        }
        return buffer;
    }

h5

checkout.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Accept a payment</title>
    <meta name="description" content="A demo of a payment on Stripe" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="checkout.css" />
    <script src="https://js.stripe.com/v3/"></script>
    <script src="checkout.js" defer></script>
  </head>
  <body>
    <!-- Display a payment form -->
    <form id="payment-form">
      <div id="payment-element">
        <!--Stripe.js injects the Payment Element-->
      </div>
      <button id="submit">
        <div class="spinner hidden" id="spinner"></div>
        <span id="button-text">Pay now</span>
      </button>
      <div id="payment-message" class="hidden"></div>
    </form>
  </body>
</html>

checkout.js

// This is your test publishable API key.  公钥
const stripe = Stripe("pk_test_...");

let elements;

initialize();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);	

// Fetches a payment intent and captures the client secret
async function initialize() {
    
    
  const response = await fetch("http://localhost:8088/create", {
    
    
    method: "POST",
    headers: {
    
    
		"Content-Type": "application/json" 
	},
    body: JSON.stringify({
    
    
		'coinType': 'thb',
		'num': '100'
	}),
  });
  const {
    
     clientSecret } = await response.json();
  
  const appearance = {
    
    
    theme: 'stripe',
  };
  elements = stripe.elements({
    
     appearance, clientSecret });


  const paymentElement = elements.create("payment");
  paymentElement.mount("#payment-element");
}

//支付成功体跳转
async function handleSubmit(e) {
    
    
  e.preventDefault();
  setLoading(true);

  const {
    
     error } = await stripe.confirmPayment({
    
    
    elements,
    confirmParams: {
    
    
      // Make sure to change this to your payment completion page
      return_url: "http://127.0.0.1:8848/success.html",
    },
  });

  //只有当出现即时错误时,才会到达这一点确认付款。否则,您的客户将被重定向到你的“return_url”。
  //对于一些像iDEAL这样的支付方式,你的客户会首先重定向到一个中间站点,然后授权支付重定向到' return_url '。
  if (error.type === "card_error" || error.type === "validation_error") {
    
    
    showMessage(error.message);
  } else {
    
    
    showMessage("An unexpected error occurred.");
  }

  setLoading(false);
}

function setLoading(isLoading) {
    
    
  if (isLoading) {
    
    
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    
    
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}

checkout.css

/* Variables */
* {
    
    
  box-sizing: border-box;
}

body {
    
    
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  display: flex;
  justify-content: center;
  align-content: center;
  height: 100vh;
  width: 100vw;
}

form {
    
    
  width: 30vw;
  min-width: 500px;
  align-self: center;
  box-shadow: 0px 0px 0px 0.5px rgba(50, 50, 93, 0.1),
    0px 2px 5px 0px rgba(50, 50, 93, 0.1), 0px 1px 1.5px 0px rgba(0, 0, 0, 0.07);
  border-radius: 7px;
  padding: 40px;
}

.hidden {
    
    
  display: none;
}

#payment-message {
    
    
  color: rgb(105, 115, 134);
  font-size: 16px;
  line-height: 20px;
  padding-top: 12px;
  text-align: center;
}

#payment-element {
    
    
  margin-bottom: 24px;
}

/* Buttons and links */
button {
    
    
  background: #5469d4;
  font-family: Arial, sans-serif;
  color: #ffffff;
  border-radius: 4px;
  border: 0;
  padding: 12px 16px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  display: block;
  transition: all 0.2s ease;
  box-shadow: 0px 4px 5.5px 0px rgba(0, 0, 0, 0.07);
  width: 100%;
}
button:hover {
    
    
  filter: contrast(115%);
}
button:disabled {
    
    
  opacity: 0.5;
  cursor: default;
}

/* spinner/processing state, errors */
.spinner,
.spinner:before,
.spinner:after {
    
    
  border-radius: 50%;
}
.spinner {
    
    
  color: #ffffff;
  font-size: 22px;
  text-indent: -99999px;
  margin: 0px auto;
  position: relative;
  width: 20px;
  height: 20px;
  box-shadow: inset 0 0 0 2px;
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  transform: translateZ(0);
}
.spinner:before,
.spinner:after {
    
    
  position: absolute;
  content: "";
}
.spinner:before {
    
    
  width: 10.4px;
  height: 20.4px;
  background: #5469d4;
  border-radius: 20.4px 0 0 20.4px;
  top: -0.2px;
  left: -0.2px;
  -webkit-transform-origin: 10.4px 10.2px;
  transform-origin: 10.4px 10.2px;
  -webkit-animation: loading 2s infinite ease 1.5s;
  animation: loading 2s infinite ease 1.5s;
}
.spinner:after {
    
    
  width: 10.4px;
  height: 10.2px;
  background: #5469d4;
  border-radius: 0 10.2px 10.2px 0;
  top: -0.1px;
  left: 10.2px;
  -webkit-transform-origin: 0px 10.2px;
  transform-origin: 0px 10.2px;
  -webkit-animation: loading 2s infinite ease;
  animation: loading 2s infinite ease;
}

@-webkit-keyframes loading {
    
    
  0% {
    
    
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    
    
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes loading {
    
    
  0% {
    
    
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    
    
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@media only screen and (max-width: 600px) {
    
    
  form {
    
    
    width: 80vw;
    min-width: initial;
  }
}

测试

安装 Stripe CLI

下载并解压windows…zip

启动stripe cli

//cmd打开stripe.exe目录 然后回车 会打开网页授权
stripe login
//配置本地回调接口路径 这样支付结果就会通知到本地
stripe listen --forward-to http://localhost:8088/webhook
//模拟 支付成功通知
stripe trigger payment_intent.succeeded

测试账号

visa 4242 4242 4242 4242,有效期、CVC 以及邮编可任意填写。

猜你喜欢

转载自blog.csdn.net/weixin_42704356/article/details/127266623