# 站内支付

## 本模式适用于：

&#x20;               **\* 有Web或mobile端商城系统，且对支付体验有极致追求的商户**

## 概述:

&#x20;      站内支付产品致力于帮助商户在桌面和移动端构建美观、智能的结账流程，为商户的客户提供最佳支付体验。&#x20;

&#x20;      商户可以通过加载 AsiaBill sdk 在网站上展示AsiaBill托管的支付页面，可通过参数调整支付页面的布局及样式，以保持与网站的整体风格一致，无需跳转即可完成整个支付流程。&#x20;

&#x20;      站内支付产品主要适用于 [先存后付](/docs/zhi-fu/geng-duo-zhi-fu-chang-jing/xian-cun-hou-fu.md)、[付后存卡](/docs/zhi-fu/geng-duo-zhi-fu-chang-jing/fu-hou-cun-ka.md)、[循环扣款](/docs/zhi-fu/geng-duo-zhi-fu-chang-jing/xun-huan-kou-kuan.md) 等场景。

<div align="center"><img src="/files/Ru57p5dXXodIxq8TpkcW" alt="Demo效果图"></div>

<figure><img src="/files/T2vMLDf78eueP9SQ3Xiq" alt="带背景部分的效果图"><figcaption><p>带背景的效果图</p></figcaption></figure>

![站内支付流程图](/files/th8ISrVwez8qnqMVi1VI)

## 对接流程:&#x20;

### **1.创建sessionToken &#x20;**<mark style="color:blue;">**`server`**</mark>

&#x20;      商户服务端调用 [**/sessionToken** 接口](https://asiabill.gitbook.io/api-explorer/api-reference/jiao-yi/sessiontoken)创建本次交易的会话即 **sessionToken。**

{% hint style="info" %}
建议商户通过服务端调用 **`/sessionToken`** 接口通过该接口可以获取到 **`sessionToken`**，该参数会用于后续支付流程的处理，商户需要从 **server** 端传递到 **web** 端供SDK中的API使用，请妥善保存，避免 **signkey** 等信息暴露在浏览器客户端。
{% endhint %}

### **2.展示付款区域 &#x20;**<mark style="color:purple;">**`web`**</mark>

&#x20;      在浏览器端可获取 AsiaBill UI 组件收集用户卡信息，UI 组件都被包含在 `Iframe` 中，SDK收集卡号信息后可通过 `HTTPS` 协议安全地传输用户数据。

* ***加载 js sdk***

&#x20;      首先，需要加载 **`AsiabillPayment.min.js`** 到商城的 **`Checkout`** 页面。

> [ ](https://{paymentApiUrl}/static/v3/js/AsiabillPayment.min.js)https\://{[paymentApiUrl](https://asiabill.gitbook.io/api-explorer/)}/static/v3/js/AsiabillPayment.min.js

{% code title="Checkout.html" %}

```javascript
<body>
// ...
</body>
<script src="<AsiaBill SDK>"></script>
<script src="<Your script>"></script>
```

{% endcode %}

* #### ***添加表单容器***

&#x20;       商户在页面中放置 AsiaBill 支付表单的容器，AsiaBill 会在商户引入支付脚本并初始化后在此区域嵌入对应的支付表单。容器和支付按钮样式由商户自定义。

代码示例:

{% code title="Checkout.html" %}

```javascript
<div class="form-wrap">
   <form id="payment-form">
     <div id="ab-card-element" class="ab-element">
     <!-- AsiaBill 元素将在这里被创建 -->
     </div>
     <!-- 错误信息 -->
     <div id="card-errors" role="alert"></div>
     <div class="card-save">
	<input type="checkbox" id="card-save">
	Save payment information
     </div>
     <button id="ab_submit" type="submit">Pay Now</button>
   </form>
</div>
```

{% endcode %}

&#x20;

&#x20;      商户向 **elementInit API** 传入参数进行脚本初始化操作。初始化操作用于校验商户信息，以及加载付款页面。**`sessionToken`** 为商户使用脚本的唯一标识。

{% code title="Checkout.js" fullWidth="false" %}

```javascript
// 初始化sdk样式
let st = {
	frameMaxHeight: 200, //  iframe高度
	input: {
		FontSize: '16', // 输入框字体大小
		FontFamily: 'Arial', // 输入框字体类型
		FontWeight: '400', // 输入框字体粗细
		BorderRadius: '10px', // 输入框圆角
		Color: '#333', // 输入框字体颜色
		ContainerBorder: '1px solid #d9d9d9', // 输入框边框
		ContainerPadding: '20px 10px', // 输入框内边距
		ContainerBg: '#fff', // 输入框背景色
		ContainerSh: 'none' // 输入框阴影
	},
	// 需要展示背景区域时可，自定义的样式
	background: {
		FontSize: '14', // 背景区域字体大小
		FontFamily: 'Arial', // 背景字体类型
		FontWeight: '600', // 背景字体粗细
		Color: #333, // 背景字体颜色
		BgColor: '#fff', // 背景颜色
		Width: '100%', // 背景宽度
		Height: 'auto', // 背景高度
		BgPadding: '20px', // 背景内边距
		BorderRadius: '10px', // 背景圆角
		TextIndent: '10px', // 背景文本缩进
		LineHeight: '24px', // 背景文本行高
		BoxShadow: 'none' // 背景阴影
	}
}
let p = {
	formId: 'payment-form', // 页面表单id
	formWrapperId: 'ab-card-element', // 表单内层id
	frameId: 'PrivateFrame', // 生成的IframeId
	customerId: '<当前支付流程的客户Id>',
	lang: 'en', // 表单校验信息国际化参数，目前支持ar(阿拉伯语),ja(日语),ko(韩语),en(英语),zh-CN(简体中文)；不传时如果当前浏器语言为日语、韩语、英语和简体中文中的一种，则会显示该种语言；否则默认展示英语
	needCardList: true,
	autoValidate: true, // 是否自动展示校验错误信息， 目前支持在表单提交事件或提交按钮点击事件中触发信息校验，false时监听`getErrorMessage`事件获取错误信息
	supportedCards: ['visa', 'jcb', 'unionPay', 'ae', 'master', 'discover'], // 传入时，显示商户支持的卡种类型logo
	layout: {
		pageMode: 'block', // 页面风格模式  inner | block
		style: st
	}	
}
let ab = AsiabillPay("<your sessionToken>");
ab.elementInit("payment_steps", p).then((res) => { 
	// 初始化成功后，商户可以在此区域执行其他操作。
	// 例如，不需要sdk自带的支付方式列表效果时,获取列表内容后可自定义展示效果。
	let paymentMethodList = res.data.paymentMethodList; 
	if (paymentMethodList.length > 0) {
		// your code 
	}
	console.log("initRES", res) 
}).catch(function(err) { 
	console.log("initERR", err) 
});

// 更新sdk样式(可选)，通过该方法可动态改变sdk样式。例如：通过监听视图宽度时调用
// ab.updateStyle(param)中的param为初始化sdk中定义的st变量
ab.updateStyle(st).then(upRes => {
// {'code': '0000', 'message': 'success'}
	console.log("updateStyle------------ ", upRes)
})
```

{% endcode %}

{% hint style="info" %}
调用 **payment\_steps** 方法时，参数 **layout.pageMode** 代表生成的页面风格模式，该参数提供 **inner** 和 **block** 两种值。

**·** **inner** 表示 卡号&过期时间\&CVV 在一行展示，详见以下付款区域示例图；

**·** **block** 表示 卡号 在第一行展示，过期时间\&CVV 在第二行展示。详见[多行模式demo](https://testpay.asiabill.com/static/v3/Checkout_block_v2.html)
{% endhint %}

&#x20;     初始化成功后，商户将看到以下付款区域：

![](/files/gbbJMoDNByrUHedU5PLx)

&#x20;      如果商户在初始化时传&#x5165;**`needCardList: true`**&#x548C;**`needCardLogo: true`，**&#x7528;户将看到带支付方式列表的托管区域：

![](/files/YxkrNU7VydMoR3ZIswjh)

{% hint style="info" %}
如果用户是注册会员，可以展示'Save payment information'选项，商家通过`/customers`接口创建`customerId`，并与商家系统中的会员账号关联。

如果是guest用户，不建议展示'Save payment information'选项。
{% endhint %}

&#x20;

&#x20;

### **3.创建支付方式&#x20;**<mark style="color:purple;">**`web`**</mark>

&#x20;      商户通过监听表单提交或者按钮点击事件，调用 **confirmPaymentMethod API** 来完成对卡号的保存，如果执行成功，SDK将会给商户返回 **`customerPaymentMethodId`**，作为该支付方式的标识。

{% hint style="info" %}
如果需要将当前客户&#x7684;**`customerId`**&#x4E0E;卡号进行绑定，请在 **confirmPaymentMethod API** 中传入 **`customerId`。**&#x5426;则，**`customerId`** 可不传。
{% endhint %}

代码示例:

{% code title="Checkout.js" %}

```javascript
let paymentMethodObj = {
  "billingDetail": {
	"address": {
		"city": "sz",
		"country": "CN",
		"line1": "line",
		"line2": "",
		"postalCode": "518000",
		"state": "state"
	},
	"email": "lcq@gmail.com",
	"firstName": "CL",
	"lastName": "BRW1",
	"phone": "13249432555"
  },
  "customerId": "<当前支付流程的客户Id>"
}
let form = document.getElementById(formId);
form.addEventListener('submit', (e) => {
      e.preventDefault();
      ab.confirmPaymentMethod({
      	apikey: "your sessionToken",
      	trnxDetail: paymentMethodObj
      }).then((result) => {
	console.info("PaymentMethodObject_Result", JSON.stringify(result));
        let r = result;
        if (r.data.code === "success") {
          // your code
          } else {
            console.log(r.data.message);
          }
      });
});
```

{% endcode %}

&#x20;

### **4.发起扣款 &#x20;**<mark style="color:blue;">**`server`**</mark>

&#x20;      商户可通过服务端调用[/confirmCharge](https://asiabill.gitbook.io/api-explorer/api-reference/jiao-yi/confirm-charge)发起扣款业务。

### 5. 验证签名

&#x20;      根据 [数据签名过程](https://asiabill.gitbook.io/api-explorer/fu-lu/shu-ju-qian-ming-guo-cheng) 验证返回信息

### **6.处理支付结果**

1. 返回结果中redirectUrl为空，则不需要进行3DS验证，将解析后的交易结果返回给前端，前端跳转用户到交易结果展示页面
2. 返回结果中redirectUrl不为空，则需要进行3DS验证，将解析后的redirectUrl返回给前端，前端跳转用户到3DS页面进行验证
   1. 3DS验证完成后，AsiaBill将跳转到商户的returnUrl地址（请参阅 [支付结果跳转](https://asiabill.gitbook.io/api-explorer/webhook/zhi-fu-jie-guo-tiao-zhuan) ），商户端验证签名并解析数据后，将解析结果（成功、失败）返回给前端，前端跳转用户到交易结果展示页面

### 7.webhook 通知处理

&#x20;      在订单完成后，AsiaBill系统会触发webhook，调用商户交易时给定的callbackUrl，来通知商户交易结果状态，详情请参阅 [webhook](https://asiabill.gitbook.io/api-explorer/webhook/gai-shu)

{% hint style="danger" %}
仅接收浏览器端的支付结果是存在风险的，商户网站可能因用户网络或者用户关闭网页导致不能获取到支付结果。建议商户接收 AsiaBill 的支付结果异步通知，可以通过在 [**创建订单**](#2.-chuang-jian-ding-dan) 步骤中设置 **callbackUrl** 来指定接收地址。
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://asiabill.gitbook.io/docs/zhi-fu/zai-xian-zhi-fu/zhan-nei-zhi-fu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
