放慢了步伐,只为跑得更远~

0%

关于海外支付SDK的集成方案与总结

前言

因为业务的需要,公司的游戏不断的向海外拓展.自然地,我们的游戏也要根据当地的需要接入不同的支付方式.其中,最具代表性的,首当其冲的非苹果支付和谷歌支付莫属.但是,除此之外也有其他的支付方式,比如PayPal,Mycard等等.

PayPal支付

相对于国外其他的第三方支付,Paypal支付算是一个比较容易上手的第三方支付.Paypal支付移动SDK继承三种方式的支付,如下所示:

  • a) 接受信用卡和Paypal支付: 开发者能够简单地将Paypal支付和信用卡支付集成到应用中,信用卡支付手动支付和扫码支付.
  • b) 未来支付: 一旦客户将Paypal账户授权给开发者的应用中,使用Paypal支付时无需再次登录即可完成付款.
  • c) 原生支付: 用户付款时无需重定向到新页面即可完成付款

OAuth2协议

  • 1)开发者使用key和secret向Paypal服务器请求token(OAuth2协议).
  • 2)之后的请求都需要携带token认证完成操作.
  • 3)用户支付成功之后,服务端需要将利用客户端回传的数据向Paypal发起支付确认.
  • 4)当token过期失效是重新获取Token.

获取授权Token

开发者从开发者后台相应的应用上获取client_id和secret.通过这两个秘钥串想服务器请求token.

1
2
3
4
5
curl -v https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
-u "client_id:secret" \
-d "grant_type=client_credentials"

请求成功之后,响应的参数格式数如下所示:
其中, Access-Token 表示获取到token值.expires_in表示该token的过期时间.scope表示授权可请求的权限.

1
2
3
4
5
6
7
8
{
"scope": "https://uri.paypal.com/services/subscriptions https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://uri.paypal.com/services/applications/webhooks openid https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.*",
"nonce": "2017-06-08T18:30:28ZCl54Q_OlDqP6-4D03sDT8wRiHjKrYlb5EH7Di0gRrds",
"Access-Token": "Access-Token",
"token_type": "Bearer",
"app_id": "APP-80W284485P519543T",
"expires_in": 32398
}

支付验证

开发者通过将结合用户支付成功之后从客户端回传的参数(订单号)向Paypal服务器指定的API请求支付验证.此时需要在请求头中携带token.

1
2
3
curl https://api.sandbox.paypal.com/v1/payments/payment/PAY-5YK922393D847794YKER7MUI \
-H "Content-Type: application/json" \
-H "Authorization: Bearer accessToken"

请求成功之后,响应的参数格式如下所示:
其中,environment表示请求的支付环境,分为sandbox(沙盒模式)和正式模式(live).state表示支付状态,approved表示支付验证已通过. 开发者可以通过对响应值携带的相关参数进行二次验证.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"client":{
"environment":"sandbox",
"paypal_sdk_version":"2.0.0",
"platform":"iOS",
"product_name":"PayPal iOS SDK;"
},
"response":{
"create_time":"2014-02-12T22:29:49Z",
"id":"PAY-564191241M8701234KL57LXI",
"intent":"sale",
"state":"approved"
},
"response_type":"payment"
}

Mycard支付

Mycard支付是一个主要面向港澳台地区游戏充值代币平台,它的主要优势在于能够因地适宜的提供适合当地支付方式.按照交易模式来划分,主要分为网页支付和客户端支付两种.而按照付费方式来划分,又可以分为卡片支付、会员扣点交易、小额付款交易.

申请交易授权码

研发商在进行所有的相关的交易之前,需要向Mycard服务端申请授权码.当交易模式为Web,付费方式为INGAME,充值服务为Server-side时,此时进入网页版本支付模式.否则就是客户端支付.

客户端支付

支付流程

  • 客户端通过API向服务端发起请求,由服务端代客户端向Mycard服务端申请相关的授权码.服务端相关的代码如下所示.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getMyCardAuthCode($arrData){
$arrGetMyCardAuthWhere = array(
"FacServiceId" => $this->arrConfigSDK['FacServiceId'],
"FacTradeSeq" => $arrData['FacTradeSeq'],
"TradeType" => $this->arrConfigSDK['TradeType'],
"ServerId" => $arrData['ServerId'],
"CustomerId" => $arrData['CustomerId'],
"PaymentType" => "",
"ItemCode" => "",
"ProductName" => strtolower(urlencode($arrData['ProductName'])),
"Amount" => $arrData['Amount'],
"Currency" => strtoupper($arrData['Currency']),
"SandBoxMode" => $this->arrConfigSDK['sandBox'],
);
$signature = $this->getPaySign($arrGetMyCardAuthWhere);
$arrGetMyCardAuthWhere['Hash'] = $signature;
$rootUrlMyCard= $this->arrConfigSDK['sandBox'] ? self::urlMyCardAuthTest : self::urlMyCardAuthB2B;
$urlMyCard = $rootUrlMyCard."?".urldecode(http_build_query($arrGetMyCardAuthWhere,NULL,"&"));
$arrGetMyCardAuth = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCardAuth);
return empty($arrGetMyCardAuth) ? array() : json_decode($arrGetMyCardAuth,true);
}
  • 客户端获取相应的授权码之后,在SDK内发起支付请求唤起支付界面,再由玩家进行支付操作.
  • 当玩家在游戏内成功完成交易之后,将申请得到的授权码再回传给我服务端请求发货.
  • 服务端获取到授权码之后先去验证交易结果,然后再进行请款,最后在请求发货.
1
2
3
4
5
6
7
8
9
10
11
12
13
function getMyCardTradeQuery($arrData){
if(!empty($arrData['AuthCode'])){
$arrAuthCode = array(
"AuthCode" => $arrData['AuthCode']
);
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardQueryTest : self::urlMyCardQueryB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrAuthCode,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
function getMyCardPaymentConfirm($arrData){
if(!empty($arrData['AuthCode'])){
$arrAuthCode = array(
"AuthCode" => $arrData['AuthCode']
);
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardConfirmTest : self::urlMyCardConfirmB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrAuthCode,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}

网页版支付

进入网页版支付模式下,网页支付可分为自定义页面以及官方推荐页面.

支付流程

  • 玩家选择指定的充值档位之后需要通过Ajax向服务端发起请求,由服务端代网页端向Mycard服务端申请相关的授权码.服务端相关的代码略.
  • 玩家需要填写支付的点卡信息,网页需要将授权码和相关的点卡信息给服务端先进行验证,再进行请款,最后再请求发货.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function getMyCardPayInGamePay($arrData){
if(!empty($arrData['AuthCode']) && !empty($arrData['CardID']) && !empty($arrData['CardPW'])){
$arrMyCardInGamePayWhere = array(
"AuthCode" => $arrData['AuthCode'],
"CardID" => $arrData['CardID'],
"CardPW" => $arrData['CardPW'],
);
$signature = $this->getPaySign($arrMyCardInGamePayWhere);
$arrMyCardInGamePayWhere['Hash'] = $signature;
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardInGamePayTest : self::urlMyCardInGamePayB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrMyCardInGamePayWhere,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}

思考

参考资料

-------------本文结束感谢您的阅读-------------